将vector::resize()的大小调整为较低计数时重新分配的空间

Space reallocated in vector::resize() when resized to lower count?

本文关键字:新分配 空间 分配 resize vector 调整      更新时间:2023-10-16

根据Stroustrup:C++编程语言:-

"当向量被调整大小以容纳更多(或更少)元素时,其所有元素可能移动到新位置。">

即使向量被重新调整为更小的大小,这是否成立?

情况1:如果请求的新大小大于当前std::vector::capacity(),则将重新定位所有元素
情况2:如果请求的新大小小于当前std::vector::capacity(),则不会重新定位元素。


标准证据:

本标准将vector::resize()的作用定义为:

C++11标准23.3.6.3/12矢量容量:

void resize(size_type sz, const T& c);

效果:

if (sz > size())
insert(end(), sz-size(), c);
else if (sz < size())
erase(begin()+sz, end());
else
; // do nothing

正如@DavidRodríguez dribeas正确指出的,std::vector::insert()操作的迭代器无效规则是:

23.3.6.5矢量修饰符

1[插入,推送_返回,模板,模板_返回]

备注:如果新大小大于旧容量,则导致重新分配。如果没有重新分配,则插入点之前的所有迭代器和引用都保持有效。

本质上,这意味着:插入点之前的所有迭代器和引用都将不受影响,除非新的容器大小大于以前的容量,因为在这种情况下,所有元素都可能被移动到新的位置,从而使指向原始位置的指针/迭代器无效。由于resize()只擦除/插入容器末尾的元素[注1]。控制因素可以归结为所请求的大小相对于当前容量。

因此产生了情况1的结果。

情况2中,将调用std::vector::erase(),这种情况下的无效规则为:

23.3.6.5矢量修饰符

迭代器擦除(const_iterator位置);

3效果:在擦除点处或之后使迭代器和引用失效。

由于[注1],元素将只在结束时删除,不需要重新定位所有元素。

。。。元素可以被移动到新的位置。">

请注意它表示可以移动的方式。因此,这意味着它取决于它是什么样的大小调整。

向量中的迭代程序无效有两个原因。在迭代器的位置之前插入/删除一个元素(1),或者如果向量需要增加其容量,则重新定位整个缓冲区(2)。这里的关键是更改capacity()

因为resize()仅从容器的末端插入/移除。当向量收缩时,只有那些引用被移除元素的迭代器才会失效。当向量增长时,如果新的大小小于capacity(),则没有迭代器将无效,如果新大小较大,则所有迭代器都将无效。

由于Als提供了不正确的证据1,我在这里添加了正确的引号:

23.3.6.5矢量修饰符

1[插入,推送_返回,模板,模板_返回]

备注:如果新大小大于旧容量,则导致重新分配。如果没有重新分配,则插入点之前的所有迭代器和引用都保持有效。

2[擦除]

效果:在擦除点处或之后使迭代器和引用失效。

类似的引号可以在C++03中找到。


1避免重复指示resize等效于插入或擦除的引号。这是对的。

问题正文中的答案">当调整向量大小以容纳更多(或更少)元素时,其所有元素都可能移动到新位置。">