为什么STL容器中的swap成员函数没有声明为noexcept?

时间:2014-05-20 08:06:26

标签: c++ c++11 swap noexcept

N3797开始,C ++标准要求容器的swap函数不抛出任何异常,除非另有说明[container.requirements.general]23.2.1§10)。

  • 为什么指定的swap成员函数不会抛出未声明的noexcept

同样的问题适用于专门的非成员swap重载。

2 个答案:

答案 0 :(得分:10)

what refp said之后,这是DanielKrügler在std-discussion邮件列表上的帖子:

  

将函数声明为无条件noexcept的内部策略是   在

中解释      

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3279.pdf

     

使用该论文中使用的术语,std :: vector的交换函数   合同范围缩小,即它有先决条件   参与对象的分配器。这意味着存在   呼叫者可能违反前提条件的可能性   应该允许实施以我的不同方式发出信号   而不是终止。因此,这些功能不应该是noexcept,   但它应该有一个有效的元素“投掷:没什么”因为这个   适用于满足前提条件的情况。

link

所说的内部政策是对你的问题的正式的官方回答。

答案 1 :(得分:6)

一开始可能听起来很奇怪,但没有明确说明swap标准容器是noexcept是故意的;这一切都归结为未定义的行为(UB)。


  

23.2.1p9 一般容器要求 [container.requirements.general]

     
    

表达式a.swap(b),用于标准的容器ab     除array以外的容器类型,应交换a的值     和b而不调用任何移动,复制或交换操作     个别容器元素。

         

归属于ComparePred的任何Hashab个对象     可以交换,并通过无条件的电话交换给非会员     swap

         

如果     allocator_traits<allocator_type>::propagate_on_container_swap::value     是true,然后还应交换ab的分配器     使用对非成员swap的未命名调用。 否则,他们应该     除非`a.get_allocator,否则不被交换,行为未定义     ()== b.get_allocator()。

  

注意斜体由我添加。


为什么上一部分与我的问题相关?

由于标准容器的swap具有前提条件(最重要的是标准的先前引用部分的最后一段),如果不满意可能导致 UB ,标准不希望对实施施加“不可能”的限制。


标准说明以下关于未定义的行为

  

1.3.24 未定义的行为 [defns.undefined]

     
    

本国际标准没有要求的行为。

  

只有犯罪分子,或许是推销员,会认为不是,而是当标准说“没有要求”它的确意味着没有要求”;将相关的swap函数标记为noexcept会对实现施加要求,其中应该没有。


为什么标准不要强加这样的要求?

有一篇有趣的论文(N3248)由 Alisdair Meredith John Lakos 标题为“ noexcept阻止了图书馆验证”。

简而言之,它讨论了noexcept如何阻止库实现在库代码中使用asserts(即标准库的实现),即使在调试模式下也是如此,以及它的含义。 / p>

如果C ++有一个标准化的“测试”与“生产”模式(正如论文所称),那么noexcept将有条件地应用,这将远没有问题..但是目前的情况; C ++没有“模式”。