Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STL vector reserve() and copy()

Greetings,

I am trying to perform a copy from one vector (vec1) to another vector (vec2) using the following 2 abbreviated lines of code (full test app follows):

vec2.reserve( vec1.size() );
copy(vec1.begin(), vec1.end(), vec2.begin());

While the call to vec2 sets the capacity of vector vec2, the copying of data to vec2 seems to not fill in the values from vec1 to vec2.

Replacing the copy() function with calls to push_back() works as expected.

What am I missing here?

Thanks for your help. vectest.cpp test program followed by resulting output follows.

Compiler: gcc 3.4.4 on cygwin.

Nat

/**
 * vectest.cpp
 */

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> vec1;
    vector<int> vec2;

    vec1.push_back(1);
    vec1.push_back(2);
    vec1.push_back(3);
    vec1.push_back(4);
    vec1.push_back(5);
    vec1.push_back(6);
    vec1.push_back(7);

    vec2.reserve( vec1.size() );
    copy(vec1.begin(), vec1.end(), vec2.begin());

    cout << "vec1.size()     = " << vec1.size() << endl;
    cout << "vec1.capacity() = " << vec1.capacity() << endl;

    cout << "vec1: ";
    for( vector<int>::const_iterator iter = vec1.begin(); iter < vec1.end(); ++iter ) {
        cout << *iter << " ";
    }
    cout << endl;

    cout << "vec2.size()     = " << vec2.size() << endl;
    cout << "vec2.capacity() = " << vec2.capacity() << endl;
    cout << "vec2: ";
    for( vector<int>::const_iterator iter = vec2.begin(); iter < vec2.end(); ++iter ) {
        cout << *iter << endl;
    }

    cout << endl;
}

output:

vec1.size()     = 7
vec1.capacity() = 8
vec1: 1 2 3 4 5 6 7 
vec2.size()     = 0
vec2.capacity() = 7
vec2: 
like image 715
natersoz Avatar asked Jul 14 '09 22:07

natersoz


People also ask

What is a vector copy?

Copy enables you to: define a vector of operands, copy the values or bit status of each operand within that vector, write those values or status into a corresponding vector of operands of the same length.

What does reserve function do in C++?

Introduction to C++ reserve() The C ++ reserve() function helps us in reserving a vector capacity. This capacity must be enough so that it can contain n number of elements.

What is vector Reserve?

std::vector::reserveRequests that the vector capacity be at least enough to contain n elements. If n is greater than the current vector capacity, the function causes the container to reallocate its storage increasing its capacity to n (or greater).

Does vector Reserve take up memory?

vector::reserve does allocate memory, so your question about reserving memory without allocating is incorrect. The point is that reserving memory can be done without changing the vectors size. Basically a vector has two sizes, it's size and it's capacity.


3 Answers

If the vectors are of the same type, use copy construction or copy assignment:

vec2(vec1);
vec2 = vec1;

If the vectors aren't the exact same (maybe a different allocator or something, or vec1 is a deque), what you really want is the range-based constructor or range-based assign:

vec2(vec1.begin(), vec1.end()); // range-based constructor

vec2.assign(vec1.begin(), vec1.end()); // range-based assignment

If you insist on doing it with std::copy, the proper method is:

copy(vec1.begin(), vec1.end(), back_inserter(vec2));

Since reserving the space does not make it assignable. copy works by assigning each element to its new value. So vec2.size() needs to be at least as large as vec1.size() in your case. Calling reserve doesn't actually change a vector's size, just its capacity.

In the book Effective STL, Scott Meyers argues that nearly all uses of std::copy for insertion should be replaced with range-based member functions. I suggest you pick up a copy, it's a great reference!

like image 143
rlbond Avatar answered Sep 24 '22 06:09

rlbond


As noted in other answers and comments, you should just use vector's built-in functionality for this. But:

When you reserve() elements, the vector will allocate enough space for (at least?) that many elements. The elements do not exist in the vector, but the memory is ready to be used. This will then possibly speed up push_back() because the memory is already allocated.

When you resize() the vector, it will allocate enough space for those elements, but also add them to the vector.

So if you resize a vector to 100, you can access elements 0 - 99, but if you reserve 100 elements, they are not inserted yet, just ready to be used.

What you want is something like this:

vec2.reserve( vec1.size() );
copy(vec1.begin(), vec1.end(), std::back_inserter(vec2));

std::back_inserter is defined in <iterator>

like image 40
GManNickG Avatar answered Sep 23 '22 06:09

GManNickG


Why not: vec2 = vec1; ?

like image 30
EFraim Avatar answered Sep 26 '22 06:09

EFraim