If I reserve some space for a vector, and then I copy some values in it with std::copy_n()
, I get the values copied correctly and accessible, but the size of the vector is still zero. Is this the expected behaviour? Should I resize the vector instead, even if it is not as efficient?
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<double> src, dest;
for(double x = 0.0; x < 100.0; ++x)
src.push_back(x);
dest.reserve(src.size());
std::copy_n(src.cbegin(), src.size(), dest.begin());
std::cout << "src.size() = " << src.size() << std::endl;
std::cout << "dest.size() = " << dest.size() << std::endl;
for(size_t i = 0; i < src.size(); ++i)
std::cout << dest[i] << " ";
}
Compilers tested: clang, gcc, Visual C++
The C++ function std::vector::resize() changes the size of vector. If n is smaller than current size then extra elements are destroyed. If n is greater than current container size then new elements are inserted at the end of vector.
Vectors are known as dynamic arrays which can change its size automatically when an element is inserted or deleted. This storage is maintained by container. The function alters the container's content in actual by inserting or deleting the elements from it.
Yes, size is decreased as you erase elements. Returns the number of elements in the vector.
C++ Vector Library - reserve() FunctionThe C++ function std::vector::reserve() requests to reserve vector capacity be at least enough to contain n elements. Reallocation happens if there is need of more space.
but the size of the vector is still zero
std::copy_n
won't change the size of the container, just copy the value and step the iterators; it even doesn't have any information about the container. So the code has undefined behavior, even it seems to work fine.
Should I resize the vector instead, even if it is not as efficient?
Yes you could use std::vector::resize
instead of std::vector::reserve
to solve the issue. As you might have thought, it means all the elements will be constructed by resize
firstly, then assigned by copy_n
.
You could use std::back_inserter, which will append elements at the end of the container by invoking the container's push_back()
member function (i.e. construct elements directly), thus increase the container's size. e.g.
dest.reserve(src.size());
std::copy_n(src.cbegin(), src.size(), std::back_inserter(dest));
The key thing to remember about standard library algorithms is that they operate on ranges, not containers. Containers are one of the ways that you can create ranges, but they are not the only way. Algorithms that write results into a range assume that they are writing to valid locations; they do not, and cannot, extend the range that they are writing to.
So when you call std::copy_n
you must provide a range that's large enough to hold the result. That means setting up the range with dest.resize(src.size());
, not just allocating memory with dest.reserve(std.size());
.
Alternatively, you can provide a range that knows that it's attached to a container and needs to adjust the size, by calling the algorithm with std::back_inserter(dest)
instead of dest.begin()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With