【问题标题】:Space reallocated in vector::resize() when resized to lower count?调整大小以减少计数时,在 vector::resize() 中重新分配的空间?
【发布时间】:2012-09-24 07:39:32
【问题描述】:

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

“当一个 vector 被调整大小以容纳更多(或更少)元素时,它的所有元素可能 搬到了新的位置。”

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

【问题讨论】:

  • 接受的答案是错误的,如果引用来自标准的错误部分,则提供标准的引用并不能使答案正确:)

标签: c++ stl vector


【解决方案1】:

案例 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 position);

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

由于[注1],元素只会在最后被移除,不需要重新定位所有元素。

【讨论】:

  • @DavidRodríguez-dribeas - 我不知道什么是“常规插入”,但规则是如果需要重新分配,所有迭代器和引用都将失效。因此,除非您对向量的状态有明确的了解,否则您不能假设 any 迭代器或引用仍然有效。诚然,可以编写可以确定插入是否会使所有内容无效的代码,但大多数情况不需要这种详细程度。
  • @DavidRodríguez-dribeas:我同意你的反对意见。我不知何故错过了考虑和提及capacity()size() 如何影响场景。您可以将标准中的相关resize() 引用添加到你的答案。一旦 OP 取消接受,我将删除这个答案(我不能删除,直到它被接受)
  • @DavidRodríguez-dribeas:完成。谢谢!
  • 删除了 cmets,因为它们不再适用。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

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

    23.3.6.5 矢量修饰符

    1 [插入,push_back,emplace,emplace_back]

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

    2 [擦除]

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

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


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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2012-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-24
        • 1970-01-01
        • 2023-03-30
        • 2020-07-02
        相关资源
        最近更新 更多