std::vector::resize() vs. std::vector::reserve()

2019-01-01 05:50发布

There is a thread in the comments section in this post about using std::vector::reserve() vs. std::vector::resize().

Here is the original code:

void MyClass::my_method()
{
    my_member.reserve(n_dim);
    for(int k = 0 ; k < n_dim ; k++ )
         my_member[k] = k ;
}

I believe that to write elements in the vector, the correct thing to do is to call std::vector::resize(), not std::vector::reserve().

In fact, the following test code "crashes" in debug builds in VS2010 SP1:

#include <vector>

using namespace std;

int main()
{
    vector<int> v;
    v.reserve(10);
    v[5] = 2;

    return 0;
}

Am I right, or am I wrong? And is VS2010 SP1 right, or is it wrong?

标签: c++ stl vector
6条回答
萌妹纸的霸气范
2楼-- · 2019-01-01 06:07

There are two different methods for a reason:

std::vector::reserve will allocate the memory but will not resize your vector, which will have a logical size the same as it was before.

std::vector::resize will actually modify the size of your vector and will fill any space with objects in their default state. If they are ints, they will all be zero.

After reserve, in your case, you will need a lot of push_backs to write to element 5. If you don't wish to do that then in your case you should use resize.

查看更多
临风纵饮
3楼-- · 2019-01-01 06:09

There probably should be a discussion about when both methods are called with a number that's LESS than the current size of the vector.

Calling reserve() with a number smaller than the capacity will not affect the size or the capacity.

Calling resize() with a number smaller than current size the container will be reduced to that size effectively destroying the excess elements.

To sum up resize() will free up memory whereas reserve() will not.

查看更多
路过你的时光
4楼-- · 2019-01-01 06:11

Yes you’re correct, Luchian just made a typo and is probably too coffee-deprived to realise his mistake.

查看更多
荒废的爱情
5楼-- · 2019-01-01 06:19

resize actually changes the amount of elements in the vector, new items are default constructed if the resize causes the vector to grow.

vector<int> v;
v.resize(10);
auto size = v.size();

in this case size is 10.

reserve on the other hand only requests that the internal buffer be grown to the specified size but does not change the "size" of the array, only its buffer size is changed.

vector<int> v;
v.reserve(10);
auto size = v.size();

in this case size is still 0.

So to answer your question, yes you are right, even if you reserve enough space you are still accessing uninitialized memory with the index operator. With an int thats not so bad but in the case of a vector of classes you would be accessing objects which have not been constructed.

Bounds checking of compilers set to debug mode can obviously be confused by this behavior which may be why you are experiencing the crash.

查看更多
弹指情弦暗扣
6楼-- · 2019-01-01 06:22

It depends on what you want to do. reserve does not add any elements to the vector; it only changes the capacity(), which guarantees that adding elements will not reallocate (and e.g. invalidate iterators). resize adds elements immediately. If you want to add elements later (insert(), push_back()), use reserve. If you want to access elements later (using [] or at()), use resize. So youre MyClass::my_method can be either:

void MyClass::my_method()
{
    my_member.clear();
    my_member.reserve( n_dim );
    for ( int k = 0; k < n_dim; ++ k ) {
        my_member.push_back( k );
    }
}

or

void MyClass::my_method()
{
    my_member.resize( n_dim );
    for ( int k = 0; k < n_dim; ++ k ) {
        my_member[k] = k;
    }
}

Which one you chose is a question of taste, but the code you quote is clearly incorrect.

查看更多
裙下三千臣
7楼-- · 2019-01-01 06:29

Answered here by Jan Hudec : Choice between vector::resize() and vector::reserve()

The two functions do vastly different things.

The resize() method (and passing argument to constructor is equivalent to that) will insert given number of elements to the vector (it has optional second argument to specify their value). It will affect the size(), iteration will go over all those elements, push_back will insert after them and you can directly access them using the operator[].

The reserve() method only allocates memory, but leaves it uninitialized. It only affects capacity(), but size() will be unchanged. There is no value for the objects, because nothing is added to the vector. If you then insert the elements, no reallocation will happen, because it was done in advance, but that's the only effect.

So it depends on what you want. If you want an array of 1000 default items, use resize(). If you want an array to which you expect to insert 1000 items and want to avoid a couple of allocations, use reserve().

EDIT: Blastfurnace's comment made me read the question again and realize, that in your case the correct answer is dont't preallocate manually. Just keep inserting the elements at the end as you need. The vector will automatically reallocate as needed and will do it more efficiently than the manual way mentioned. The only case where reserve() makes sense is when you have reasonably precise estimate of the total size you'll need easily available in advance.

EDIT2: Ad question edit: If you have initial estimate, than reserve() that estimate and if it turns out to be not enough, just let the vector do it's thing.

查看更多
登录 后发表回答