Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::copy_n doesn't change destination vector size

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++

like image 304
Pietro Avatar asked Feb 04 '17 16:02

Pietro


People also ask

How do I fix the size of a vector in 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.

Can you change vector size?

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.

Does vector erase change the size?

Yes, size is decreased as you erase elements. Returns the number of elements in the vector.

How do you reserve the size of a 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.


2 Answers

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));
like image 193
songyuanyao Avatar answered Sep 28 '22 02:09

songyuanyao


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().

like image 45
Pete Becker Avatar answered Sep 28 '22 02:09

Pete Becker