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
.