Baraa Baraa - 9 days ago 6
C++ Question

When appending one vector to another, why is moving the elements any cheaper than copying them?

Let's say that I have two vectors,

src
and
dst
and I want to append
src
to the end of
dst
.

I noticed that most answers regarding this task are recommending this:

dst.insert(dst.end(),
std::make_move_iterator(src.begin()),
std::make_move_iterator(src.end()));


Over this:

dst.insert(dst.end(), src.begin(), src.end());


As far as I know, pushing (inserting) elements to a vector requires allocating space for the inserted elements at the end of the vector in both cases to ensure memory contiguity, and I'm assuming that the
copy
and
move
cost is the same in this case.

Moving the objects will make them immediately destroy-able, is that the only benefit of doing so, or is there something else I'm missing?

edit:
I was in-explicitly talking about vectors of POD types.

Could you please explain that in those two cases:


  1. The vectors contain plain data, ex: int.

  2. The vectors contain class objects.


Answer

Indeed, if copying and moving an element costs the same (is in your example with elements of type int), then there is no difference.

Moving only makes a difference for elements which themselves store their data on the heap, i.e. use allocated memory (for example if the elements are std::string or std::vector<something>). In this case, moving or copying the elements makes a (potentially huge) difference (provided the move constructor and operator=(value_type&&) are properly implemented/enabled), since a move merely copies the pointer to the allocated memory, while a copy is deep: it allocates new memory and copies all data, including recursive deep copies if applicable.

As to the costs associated with the data stored in std::vector, there are some costs if the appended elements exceed capacity. In this case, the whole vector will be resized, including moving all its elements. The reason for this is that std::vector, by specification, stores all its elements in a single array. If appending containers is a frequent operation in your code, you may want to consider other containers, such as std::list or std::deque.