C++ std::vector::resize()与std::vector::reserve()的比较
关于使用C++ std::vector::resize()与std::vector::reserve()的比较,c++,stl,vector,C++,Stl,Vector,关于使用std::vector::reserve()vs.std::vector::resize() 以下是原始代码: void MyClass::my_method() { my_member.reserve(n_dim); for(int k = 0 ; k < n_dim ; k++ ) my_member[k] = k ; } 我是对的,还是错的?VS2010 SP1是对的,还是错的?是的,你是对的,Luchian刚刚输入了一个错误,可能是因为太
std::vector::reserve()
vs.std::vector::resize()
以下是原始代码:
void MyClass::my_method()
{
my_member.reserve(n_dim);
for(int k = 0 ; k < n_dim ; k++ )
my_member[k] = k ;
}
我是对的,还是错的?VS2010 SP1是对的,还是错的?是的,你是对的,Luchian刚刚输入了一个错误,可能是因为太少咖啡而意识不到自己的错误。有两种不同的方法是有原因的:
std::vector::reserve
将分配内存,但不会调整向量的大小,向量的逻辑大小与以前相同
std::vector::resize
实际上会修改向量的大小,并用默认状态的对象填充任何空间。如果它们是整数,它们都将是零
在reserve之后,在您的情况下,您将需要大量的push_back来写入元素5。
如果您不希望这样做,那么您应该使用resize
关于reserve有一点:如果您随后使用push_back添加元素,直到您达到您保留的容量,那么指向向量中数据的任何现有引用、迭代器或指针都将保持有效。因此,如果我保留1000个元素,并且大小为5,那么&vec[4]
将保持不变,直到向量有1000个元素为止。在那之后,我可以调用push_back()
,它会工作,但是先前存储的&vec[4]
指针可能不再有效。这取决于您想做什么<代码>保留
不添加任何
元素到向量
;它只会更改容量(),而
保证添加元素不会重新分配(例如。
使迭代器无效)<代码>调整大小立即添加元素。如果你愿意
要在以后添加元素(insert()
,push_back()
),请使用reserve
。如果你
要稍后访问元素(使用[]
或at()
),请使用调整大小
。所以
youreMyClass::my_方法可以是:
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_方法()
{
我的成员。清除();
我的会员预订(n_dim);
对于(int k=0;k
或
void MyClass::my_方法()
{
my_member.resize(n_dim);
对于(int k=0;k
你选择哪一个是品味的问题,但你引用的代码是
显然不正确。调整大小实际上改变了向量中的元素数量,如果调整大小导致向量增长,则默认构造新项
vector<int> v;
v.resize(10);
auto size = v.size();
向量v;
v、 调整大小(10);
自动大小=v.大小();
在这种情况下,尺寸为10
另一方面,reserve只请求将内部缓冲区增长到指定的大小,但不更改数组的“大小”,只更改其缓冲区大小
vector<int> v;
v.reserve(10);
auto size = v.size();
向量v;
v、 储备(10);
自动大小=v.大小();
在这种情况下,大小仍然为0
所以要回答你的问题,是的,你是对的,即使你保留了足够的空间,你仍然在使用索引操作符访问未初始化的内存。对于一个int,这并不坏,但是对于一个类向量,您将访问尚未构造的对象
设置为调试模式的编译器的边界检查显然会被这种行为所混淆,这可能是您遇到崩溃的原因。可能应该讨论一下何时使用小于向量当前大小的数字调用这两个方法 使用小于容量的数字调用
reserve()
,不会影响大小或容量
使用小于当前大小的数字调用resize()
,容器将减小到该大小,从而有效地销毁多余的元素
总而言之,
resize()
将释放内存,而reserve()
将不会。解释可能简单到“我错了”:DI将其标记为“太本地化”,因为@LuchianGrigore很少使用wrong@Default将“很少出错”读作“快速纠正错误”:)原始帖子中的代码已更新为正确使用resize()
,疑问已消除。主持人:如果这个问题“过于本地化”,请随意删除,如果您认为它可能会在将来帮助其他人,请保留它。当我将我的项目从vc6迁移到vs2013时,这个问题实际上消除了我的疑虑。。谢谢:)因此,对于空向量,即vec,在reserve之后,vec[1]将以段错误结束。vec[1]将是未定义的行为。std::vector::reserve
是否会防止在push_back
上偶尔复制完整数组?这只是用于C++11还是特定的std实现?看起来带有reserve和access的代码[]可以正常工作吗@Steve_Corrin未定义的行为是未定义的。它似乎能起作用。它仍然是无效代码。不允许对容器的
中不存在的元素进行索引。根据语言的定义,它们并不存在于那里。如果您的编译器决定不启动nukes和Instead,只需按您希望的方式戳/偷看RAM,那就是好运。我猜是运气不好;理想情况下,我们可以捕捉到所有程序员都会做的所有无效的事情,但祝你好运!调整大小永远不会释放内存。当大小变小时,将调用析构函数,但保留内存(容量不变)。
vector<int> v;
v.resize(10);
auto size = v.size();
vector<int> v;
v.reserve(10);
auto size = v.size();