What is the benefit of moving a range of elements in a vector vs. copying?

Viewed 161

Consider the following snippet (saw something analogous to this in a large simulation code)

std::vector<int> v1{1,2,3,4,5,6,7};
std::vector<int> v2;

std::move(v1.begin() + 2, v1.end(), back_inserter(v2));

Here, I am moving a range of elements from v1 to v2, but is there any particular advantage to doing this vs. copying? I do not actually see what the advantage of the move here would be since it's operating on a range of ints. In fact, I do not believe any move is occurring since we are dealing with POD types.

If we instead wanted to transfer the entire v1 to v2, then we could do:

v2 = std::move(v1);

The cast here would allow v2 to now own the pointer to the contiguous range of memory previously owned by v1, thus avoiding a copy.

But in the former move of a range of elements, I do not see the usefulness.

1 Answers

Here, I am moving a range of elements from v1 to v2, but is there any particular advantage to doing this vs. copying?

No. Here is all happened just a range coping, because your usage of std::move for primitive types just do coping. Therefore it does the same as simple if you would have:

std::vector<int> v2{v1.begin() + 2, v1.end()};

Therefore you are correct about the findings. However, it is called fundamental types/ primitive types, not PODs.


But in the former move of a range of elements, I don't see the usefulness.

Consider the case of std::vector</*expensive copy type*/>, in which it makes sense to have a move of the underlying range elements, whenever is possible.

For instance consider the std::vector<std::string> case

std::vector<std::string> v1{ "1","2","3","4","5","6","7" };
std::vector<std::string> v2;
// reserve memory for unwanted reallocations
v2.reserve(std::distance(v1.begin() + 2, v1.end()));

// moves the string element in the range
std::move(v1.begin() + 2, v1.end(), back_inserter(v2));

// v1 now: 1 2
// v2 now: 3 4 5 6 7 

(See a demo here)


As a side note, instead of std::move the range in a separate line, for iterators, one could also use std::make_move_iterator, to do the range move construction while declaration (if make sence).

#include <iterator> // std::make_move_iterator

std::vector<std::string> v1{ "1","2","3","4","5","6","7" };
std::vector<std::string> v2{ std::make_move_iterator(v1.begin() + 2),
   std::make_move_iterator(v1.end()) };
Related