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

Ral*_*zky 13 c++ swap noexcept c++11

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

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

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

Lig*_*ica 10

什么REFP说,这里是丹尼尔Krügler帖子上std-discussion的邮件列表:

将函数声明为无条件noexcept的内部策略将在下面解释

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

使用该论文中使用的术语,std :: vector的交换函数具有缩小的契约,即它具有关于参与对象的分配器的先决条件.这意味着,呼叫者可能违反前提条件,并且应该允许实施方式通过终止来表示我的不同方式.因此,这些函数不应该是noexcept,但它应该有一个有效的元素"Throws:Nothing",因为这适用于满足前提条件的情况.

(链接)

所述内部政策是对您的问题的规范,官方回答.


Fil*_*efp 6

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


23.2.1p9 一般集装箱要求 [container.requirements.general]

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

任何Compare,Pred或者Hash对象属于a并且b应该是可以交换的,并且应该通过无条件的呼叫交换给非成员 swap.

如果 allocator_traits<allocator_type>::propagate_on_container_swap::valuetrue,那么也应该使用对非成员的未经授权的呼叫来交换a和的分配器.否则,它们不会被交换,并且行为是未定义的,除非`a.get_allocator()== b.get_allocator().bswap

注意:斜体添加了我.


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

由于swap标准容器具有前提条件(最重要的是标准的先前引用部分的最后一段),如果不满足可能导致UB,标准不希望对实现施加"不可能"的约束.


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

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

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


只有犯罪分子,或许是销售人员,才会认为No不是No,而是当标准说"没有要求"时, 它实际上意味着" 没有要求" ; 标记相关swap功能noexcept将对实施施加要求,其中应该没有.


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

Alisdair MeredithJohn Lakos就此问题发表了一篇有趣的论文(N3248),标题为" 防止图书馆验证 ".noexcept

简而言之,它讨论了如何noexcept防止库实现asserts在库代码中使用(即标准库的实现),甚至在调试模式期间,以及它的含义.

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