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

Why are the swap member functions in STL containers not declared noexcept?

本文关键字:声明 noexcept 函数 成员 STL 交换 为什么      更新时间:2023-10-16

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

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

同样的问题也适用于特殊的非成员swap重载。

进一步说明refp所说的,这里是Daniel kr gler在std-discussion邮件列表上的一篇文章:

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

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

用那篇论文中使用的术语,std::vector的交换函数有一个缩小的合同,它有先决条件吗参与对象的分配器。这意味着存在调用者违反前提条件的可能性应该允许实现以不同的方式发出信号而不是终止。因此,这些功能不应该是不例外的,但它应该有一个有效的元素"抛出:无",因为这用于满足前提条件的情况。

(链接)

上述内部政策是对你的问题的规范的官方回答。

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


23.2.1p9 集装箱通用要求 [container.requirements.general]

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

任何属于abComparePredHash对象可互换,可通过无条件呼叫非会员进行交换swap .

如果allocator_traits<allocator_type>::propagate_on_container_swap::valuetrue,那么ab的分配器也要交换使用非限定调用非成员swap否则,他们应当不被交换,并且行为是未定义的,除非` .get_allocator . `() == b.get_allocator ().

<一口> 注意: 斜体添加我。


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

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


标准对未定义行为有如下规定:

1.3.24 未定义行为 [defns.undefined]

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


只有罪犯,也许还有推销员,才会认为No不是No,但是当标准说"无要求"时,它实际上是指"要求";将相关的swap函数标记为noexcept将对实现施加要求,而本应没有。


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

关于这个问题,Alisdair MeredithJohn Lakos发表了一篇有趣的论文(N3248),题为" noexcept阻止库验证"。

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

如果c++有一个标准化的"测试"与"生产"模式(如论文所称),其中noexcept将有条件地应用,这将会少得多的问题。但就目前的情况来看;c++没有"modes"