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

在这篇文章的评论部分有一个关于使用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()

事实上,以下testing代码在VS2010 SP1的debugging版本中“崩溃”:

 #include <vector> using namespace std; int main() { vector<int> v; v.reserve(10); v[5] = 2; return 0; } 

我是对的,还是我错了? 和VS2010 SP1是对的,还是错了?

有两种不同的方法是有原因的:

std::vector::reserve会分配内存,但是不会调整你的向量,它的逻辑大小和以前一样。

std::vector::resize实际上会修改你的向量的大小,并将填充任何空间的对象在其默认状态。 如果他们是整数,他们将全部为零。

在保留之后,对于你的情况,你将需要大量的push_backs来写入元素5.如果你不想这样做,那么在你的情况下,你应该使用resize。

Jan Hudec在这里回答: vector :: resize()和vector :: reserve()之间的select

这两个function做了很大不同的事情。

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

reserve()方法只分配内存,但保持未初始化。 它只影响容量(),但size()将保持不变。 对象没有任何价值,因为没有任何东西被添加到向量中。 如果插入元素,则不会进行重新分配,因为这是事先完成的,但这是唯一的影响。

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

编辑:Blastfurnace的评论让我再次阅读这个问题,并认识到,在你的情况下,正确的答案是不会预先分配手动。 只要继续插入元素在你需要的尽头。 该vector将根据需要自动重新分配,并且比上述手动方式更有效。 reserve()有意义的唯一情况是,当您对总大小进行合理的精确估计时,您需要提前轻松获得这些大小。

编辑2:广告问题编辑:如果你有最初的估计,比保留()估计,如果结果是不够的,只是让vector做的事情。

这取决于你想要做什么。 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; } } 

你select哪一个是品味的问题,但你引用的代码显然是不正确的。

是的,你是错的,陆just只是犯了一个错字,可能太不喝咖啡了,不知道自己的错误。

可能应该讨论两种方法何时被调用的数量less于vector的当前大小。

使用小于容量的数字调用reserve()不会影响大小或容量。

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

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

resize实际上改变了向量中的元素的数量,如果resize导致向量增长,则新的项目是默认构build的。

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

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

另一方面保留内部缓冲区只能请求增长到指定的大小,但不改变数组的大小,只改变其缓冲区大小。

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

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

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

编译器设置为debugging模式的边界检查显然可能会被这种行为所困惑,这可能是您遇到崩溃的原因。