Home > Enterprise >  The Interaction between std::array, std::vector, and std::copy
The Interaction between std::array, std::vector, and std::copy

Time:08-26

I am trying to copy a std::array into a std::vector using std::copy.

According to the cppReference, the prototype of std::copy is:

std::copy(InputIt first, InputIt last, OutputIt d_first)

, where OutputIt d_first stands for the beginning of the destination range.

By following the implementation, I have the following code:

std::array<int, 10> arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

std::vector<int> vec;

std::copy(arr.begin(), arr.end(), vec.begin());

However, the code did not work as I have expected, it simply does not copy the array into the vector.

Based on a quick googling, the code should be:

std::array<int, 10> arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

std::vector<int> vec;

std::copy(arr.begin(), arr.end(), std::back_inserter(vec));

My question is, why is the first code not working?

Is vec.begin() not considered as OutputIt d_first, in which my understanding would be "an iterator that represents the first position of the destination"?

CodePudding user response:

vec.begin() is an output iterator and there is in principle no problem with using it in the way you are trying to. However vec.begin() is an iterator to the beginning of the range currently held by the vector. It is not an iterator that appends to the vector.

Since your vector is initially empty, the valid range to which vec.begin() refers is also empty, but you are then trying to assign multiple elements into that range with the std::copy call, causing undefined behavior.

On the other hand std::back_inserter(vec) is not an iterator over the range currently held by the vector, but instead a pure output iterator that appends a new element to the container each time it is assigned to.

Had you resized the vector before using vec.begin() to std::copy it would have been fine as well, since the range would to which vec.begin() refers would then be large enough to hold all of the elements from the array you are copying from:

std::vector<int> vec(arr.size());
std::copy(arr.begin(), arr.end(), vec.begin());

You are also able to just write

std::vector<int> vec(arr.begin(), arr.end());

which will directly determine the correct size to allocate for the vector's storage and copy the elements of the array into it. That is more efficient than either of the other two options.


Since C 17 you can also drop the value type if you want it to be equal to that of the array. It can be deduced via CTAD:

std::vector vec(arr.begin(), arr.end());

Starting with C 23 you will also be able to just write

std::vector vec(arr);

for the same effect.

CodePudding user response:

std::array<int, 10> arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int> vec;
std::copy(arr.begin(), arr.end(), vec.begin());

My question is, why is the first code not working?

It's because vec is empty. As soon as std::copy starts writing into it, it'll write out of bounds.

You'll either have to use the back_inserter which uses the container's push_back method to add elements - or resize the vector before doing the copy.

  • Related