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模式的边界检查显然可能会被这种行为所困惑,这可能是您遇到崩溃的原因。