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

时间:2012-10-23 11:19:35

标签: c++ stl vector

this post的评论部分中有一个关于使用std::vector::reserve()std::vector::resize()的帖子。

以下是原始代码:

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

我认为要在vector中编写元素,正确的做法是调用 std::vector::resize() ,而不是std::vector::reserve()

实际上,以下测试代码在VS2010 SP1的调试版本中“崩溃”:

#include <vector>

using namespace std;

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

    return 0;
}

我是对的,还是我错了?并且VS2010 SP1是对的,还是错了?

6 个答案:

答案 0 :(得分:94)

出于某种原因,有两种不同的方法:

std::vector::reserve将分配内存,但不会调整您的矢量大小,其逻辑大小与以前相同。

std::vector::resize实际上会修改矢量的大小,并将填充处于默认状态的对象的任何空间。如果它们是整数,它们都将为零。

保留后,在你的情况下,你需要很多push_backs来写入元素5。 如果您不希望这样做,那么在您的情况下,您应该使用调整大小。

答案 1 :(得分:21)

Jan Hudec Choice between vector::resize() and vector::reserve()

回答
  

这两个功能完全不同。

     

resize()方法(以及传递给构造函数的参数等价于此)将向向量插入给定数量的元素(它具有可选的第二个参数来指定它们的值)。它将影响size(),迭代将遍历所有这些元素,push_back将在它们之后插入,您可以使用operator []直接访问它们。

     

reserve()方法只分配内存,但保留未初始化状态。它只影响capacity(),但size()将不变。对象没有值,因为向量中没有添加任何内容。如果然后插入元素,则不会重新分配,因为它是事先完成的,但这是唯一的效果。

     

所以这取决于你想要什么。如果需要1000个默认项的数组,请使用resize()。如果您想要一个数组,您希望插入1000个项目,并希望避免一些分配,请使用reserve()。

     编辑:Blastfurnace的评论使我再次阅读了这个问题并意识到,在您的情况下,正确的答案是不要手动预分配。只需根据需要在元素末端插入元素即可。向量将根据需要自动重新分配,并且比上述手动方式更有效。 reserve()有意义的唯一情况是,您需要提前轻松获得所需总大小的合理精确估计。

     

EDIT2:广告问题编辑:如果您有初步估算值,那么估计值为reserve(),如果结果不够,只需让矢量做就好了。

答案 2 :(得分:11)

这取决于你想做什么。 reserve 添加任何内容 vector的元素;它只会更改capacity() 保证添加元素不会重新分配(例如 使迭代器无效)。 resize会立即添加元素。如果你想 要稍后添加元素(insert()push_back()),请使用reserve。如果你 想要稍后访问元素(使用[]at()),请使用resize。所以 你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 );
    }
}

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

您选择的是品味问题,但您引用的代码是 显然不正确。

答案 3 :(得分:2)

是的,你是对的,Luchian只是写了一个错字,而且可能太缺乏咖啡而无法实现他的错误。

答案 4 :(得分:2)

可能应该讨论何时调用两个方法的数字比矢量的当前大小少。

使用小于容量的数字拨打reserve()不会影响尺寸或容量。

使用小于当前大小的数字调用resize(),容器将减少到该大小,从而有效地摧毁多余的元素。

总结resize()将释放内存,而reserve()则不会。

答案 5 :(得分:1)

调整大小实际上会更改向量中的元素数量,如果调整大小导致向量增长,则新项目将默认构造。

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

在这种情况下,大小为10。

另一方面,

保留只请求内部缓冲区增长到指定大小但不改变数组的“大小”,只改变其缓冲区大小。

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

在这种情况下,大小仍为0。

所以要回答你的问题,是的,你是对的,即使你保留足够的空间,你仍然使用索引运算符访问未初始化的内存。使用一个不那么糟糕的int但是在类向量的情况下,您将访问尚未构造的对象。

对于设置为调试模式的编译器的边界检查显然会被这种行为混淆,这可能是您遇到崩溃的原因。