2

根据Stroustrup 的说法:C++ 编程语言:-

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

即使将矢量重新调整为更小的尺寸,这是否成立?

4

4 回答 4

4

情况 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],元素只会在最后被删除,不需要重新定位所有元素。

于 2012-10-03T11:31:36.737 回答
1

...元素可能会移动到新位置。”

注意它所说的可能会被移动。所以这意味着这取决于它是什么类型的调整大小。

于 2012-10-03T11:23:49.497 回答
1

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

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

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

23.3.6.5 矢量修饰符

1 [插入,push_back,emplace,emplace_back]

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

2 [擦除]

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

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


1避免重复指示resize插入或擦除等价的引用。哪个是对的。

于 2012-10-03T13:08:58.830 回答
0

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

于 2012-10-03T11:31:09.890 回答