根据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 [插入,push_back,emplace,emplace_back]
备注:如果新大小大于旧容量,则导致重新分配。如果没有发生重新分配,则插入点之前的所有迭代器和引用仍然有效。
本质上这意味着:插入点之前的所有迭代器和引用都将不受影响,除非新容器大小大于先前的容量,因为在这种情况下,所有元素都可能被移动到新位置,从而使指向原始位置的指针/迭代器无效。由于resize()
仅在容器末尾擦除/插入元素[注 1]。控制因素归结为根据当前容量请求的大小。
因此,案例 1 的结果。
在案例 2 std::vector::erase()
中将被调用,并且在这种情况下的无效规则是:
23.3.6.5 矢量修饰符
迭代器擦除(const_iterator 位置);
3 效果:在擦除点处或之后使迭代器和引用无效。
由于[Note 1],元素只会在最后被删除,不需要重新定位所有元素。
...元素可能会移动到新位置。”
注意它所说的可能会被移动。所以这意味着这取决于它是什么类型的调整大小。
向量中的迭代器因两个原因而无效。如果向量需要增加其容量,则在迭代器 (1) 的位置之前插入/删除元素或重新定位整个缓冲区 (2)。这里的关键是对capacity()
.
因为resize()
只从容器的末尾插入/删除。当向量收缩时,只有那些引用被删除元素的迭代器才会失效。当向量增长时,如果新大小小于 ,则没有迭代器会失效,如果新大小大于capacity()
,则所有迭代器都将失效。
由于 Als 提供了不正确的证据1,因此我在此处添加了正确的引号:
23.3.6.5 矢量修饰符
1 [插入,push_back,emplace,emplace_back]
备注:如果新大小大于旧容量,则导致重新分配。如果没有发生重新分配,则插入点之前的所有迭代器和引用仍然有效。
2 [擦除]
效果:在擦除点或擦除点之后使迭代器和引用无效。
类似的引用可以在 C++03 中找到。
1避免重复指示resize
插入或擦除等价的引用。哪个是对的。
问题正文中的答案“”当调整向量的大小以容纳更多(或更少)元素时,它的所有元素都可能被移动到新位置。“”