简体   繁体   English

std::vector::resize() 与 std::vector::reserve()

[英]std::vector::resize() vs. std::vector::reserve()

There is a thread in the comments section in this post about using std::vector::reserve() vs. std::vector::resize() .这篇文章的评论部分有一个关于使用std::vector::reserve()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() .我相信要在vector写入元素,正确的做法是调用std::vector::resize() ,而不是std::vector::reserve()

In fact, the following test code "crashes" in debug builds in VS2010 SP1:事实上,以下测试代码在 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? VS2010 SP1 是对的,还是错的?

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::reserve将分配内存但不会调整向量的大小,向量的逻辑大小与以前相同。

std::vector::resize will actually modify the size of your vector and will fill any space with objects in their default state. std::vector::resize实际上会修改向量的大小,并将用处于默认状态的对象填充任何空间。 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.保留后,在您的情况下,您将需要大量 push_backs 来写入元素 5。如果您不想这样做,那么在您的情况下,您应该使用调整大小。

One thing about reserve: if you then add elements with push_back, until you reach the capacity you have reserved, any existing references, iterators or pointers to data in your vector will remain valid.关于保留的一件事:如果您然后使用 push_back 添加元素,直到达到您保留的容量,任何现有的引用、迭代器或指向向量中数据的指针都将保持有效。 So if I reserve 1000 and my size is 5, the &vec[4] will remain the same until the vector has 1000 elements.所以如果我保留 1000 并且我的大小是 5, &vec[4]将保持不变,直到向量有 1000 个元素。 After that, I can call push_back() and it will work, but the stored pointer of &vec[4] earlier may no longer be valid.之后,我可以调用push_back()并且它会起作用,但是之前存储的&vec[4]指针可能不再有效。

There is a thread in the comments section in this post about using std::vector::reserve() vs. std::vector::resize() .这篇文章的评论部分有一个关于使用std::vector::reserve()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() .我相信要在vector写入元素,正确的做法是调用std::vector::resize() ,而不是std::vector::reserve()

In fact, the following test code "crashes" in debug builds in VS2010 SP1:实际上,以下测试代码在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? VS2010 SP1是正确的还是错误的?

It depends on what you want to do.这取决于你想做什么。 reserve does not add any elements to the vector ; reserve添加到任何元件vector ; it only changes the capacity() , which guarantees that adding elements will not reallocate (and eg invalidate iterators).它只更改capacity() ,这保证添加元素不会重新分配(例如使迭代器无效)。 resize adds elements immediately. resize立即添加元素。 If you want to add elements later ( insert() , push_back() ), use reserve .如果您想稍后添加元素( insert()push_back() ),请使用reserve If you want to access elements later (using [] or at() ), use resize .如果您想稍后访问元素(使用[]at() ),请使用resize So youre MyClass::my_method can be either:所以你的MyClass::my_method可以是:

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.您选择哪个是品味问题,但您引用的代码显然不正确。

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.使用小于容量的数字调用reserve()不会影响大小或容量。

Calling resize() with a number smaller than current size the container will be reduced to that size effectively destroying the excess elements.使用小于当前大小的数字调用resize()容器将减小到该大小,从而有效地破坏多余的元素。

To sum up resize() will free up memory whereas reserve() will not.总结一下resize()会释放内存,而reserve()不会。

是的,你是对的,Luchian 只是打错了一个字,可能因为喝咖啡太少而无法意识到自己的错误。

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.在这种情况下,大小为 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.另一方面,reserve 仅请求将内部缓冲区增长到指定的大小,但不更改数组的“大小”,仅更改其缓冲区大小。

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

in this case size is still 0.在这种情况下,大小仍然是 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.使用 int 还不错,但在类向量的情况下,您将访问尚未构造的对象。

Bounds checking of compilers set to debug mode can obviously be confused by this behavior which may be why you are experiencing the crash.设置为调试模式的编译器的边界检查显然会被这种行为混淆,这可能是您遇到崩溃的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM