【问题标题】:Order of destruction of elements of an std::vector [duplicate]std::vector 元素的破坏顺序[重复]
【发布时间】:2011-09-04 09:02:25
【问题描述】:

可能重复:
STL containers element destruction order

是否保证std::vector 的元素会自始至终被销毁?

【问题讨论】:

  • 我想这取决于保证是否也适用于原始数组,因为 std::vector 确实模仿了数组。但我不知道标准对此有何规定。
  • @Klaim: std::vector 仅使用 op[] 语法模拟数组;这没有说明任何元素寿命保证。

标签: c++ vector destructor


【解决方案1】:

2003:5.3.5/6 说delete[]:

delete-expression 将为要删除的对象或数组的元素调用析构函数(如果有)。在数组的情况下,元素将被销毁按地址递减顺序(即,按其构造函数完成的相反顺序;参见 12.6.2)。

所以如果你的std::vector 对象的分配器使用delete[] 那么,是的,它必然会以相反的顺序销毁元素。

但是,不能保证您的 std::vector 会以这种方式工作(事实上,它很可能不会),而且我找不到任何特定于容器的引用。

真的,我认为这完全取决于您的分配器,而 2003:20.1.5(列出了对分配器的要求)似乎没有说明任何内容。

【讨论】:

  • 对它是否超出范围并调用 vector::~vector() 有什么想法?
  • 几乎可以肯定std::vector 不会使用delete[],因为合理的实现需要额外分配但未初始化的空间,构造函数没有运行(因此析构函数不应该运行) .
  • @BenVoigt:我想它使用了很多新的展示位置?
  • @Tomalek:它使用allocator_traits<allocator_type>::constructallocator_traits<allocator_type>::destroy,默认情况下,它们分别是放置 new 和显式析构函数调用的包装器。
  • @Tomalak:不仅不能保证 vector 会在包含其元素的 T 数组上调用 delete[],事实上它保证它不会 (实际上)这样做。您无法一次性实现delete[]s 的所有分配器类,因为需要destroy 一次一个的向量。 get-out 子句是“as-if”规则 - 如果向量使用默认分配器,那么它 可以 delete[] 我想,但它必须是一个特殊情况,具体取决于该实例的历史,因为vector::resize() 仍然需要以某种方式实现。
【解决方案2】:

不,数组有保证,其中所有元素的构造都是有序的,并以相反的顺序销毁。这与处理全局对象的方式有些一致。

另一方面,容器成员可以使用inserterase 成员函数以任何顺序构造和销毁。为了保持一定的一致性并以相反的构造顺序销毁元素,这将要求容器对这些更改保留某种日志。显然这会很贵!

最好的办法是容器析构函数调用clear(),它被定义为erase(begin(), end()),但我也找不到任何要求。该标准仅在表 65 中说明“线性复杂度”。

【讨论】:

  • 我不知道为什么这被否决了,因为胆小的匿名投反对票者没有发表评论。来自我的 +1
【解决方案3】:

他们标准为原始数组保证这一点,但我找不到任何可以保证容器的东西。

来自[expr.delete](C++0x 的新措辞):

如果删除表达式的操作数的值不是空指针值,删除表达式将 调用要删除的对象或数组元素的析构函数(如果有)。在一个 数组,元素将按地址递减的顺序销毁(即完成的相反顺序) 他们的构造函数;见 12.6.2)。

std::vector(实际上标准库中的所有容器,可能不包括std::array)都不会使用delete[]来销毁元素(他们在每个元素上单独使用allocator_traits<allocator_type>::destroy),所以以上保证不适用。而且我找不到关于删除顺序的特别是std::vector 或一般容器的限制。对于某些容器,这样的保证会非常昂贵(例如,std::forward_list 不能反向迭代元素来删除它们,而std::map 不记得添加对的顺序)。

来自[container.requirements.general](C++0x 措辞):

对于受本子条款影响的声明 allocator_type 的组件,存储在这些 组件应使用 allocator_traits::construct 函数和 使用 allocator_traits::destroy 函数 (20.6.8.2) 销毁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    • 2016-12-28
    • 1970-01-01
    • 1970-01-01
    • 2022-10-24
    • 2011-10-02
    • 2012-06-20
    相关资源
    最近更新 更多