从N3797开始,C ++标准要求容器的swap
函数不抛出任何异常,除非另有说明[container.requirements.general]
(23.2.1§10)。
swap
成员函数不会抛出未声明的noexcept
? 同样的问题适用于专门的非成员swap
重载。 子>
答案 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)
,用于标准的容器a
和b
除array
以外的容器类型,应交换a
的值 和b
而不调用任何移动,复制或交换操作 个别容器元素。归属于
Compare
和Pred
的任何Hash
,a
或b
个对象 可以交换,并通过无条件的电话交换给非会员swap
。如果
allocator_traits<allocator_type>::propagate_on_container_swap::value
是true
,然后还应交换a
和b
的分配器 使用对非成员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 ++没有“模式”。