13

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

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

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

4

2 回答 2

10

除了refp 所说的,这里是 Daniel Krügler 在std-discussion邮件列表中的帖子:

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

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

使用该论文中使用的术语,std::vector 的交换函数有一个收缩契约,即它对参与对象的分配器具有先决条件。这意味着,调用者可能会违反先决条件,并且应该允许实现以与终止不同的方式表示这一点。因此,此类函数不应为 noexcept,而应具有有效元素“Throws: Nothing”,因为这适用于满足前提条件的情况。

链接

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

于 2014-05-20T09:35:42.793 回答
6

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


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

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

属于and的任何Compare,PredHash对象都应是可交换的,并且应通过对 non-member 的无限制调用进行交换 。abswap

如果 allocator_traits<allocator_type>::propagate_on_container_swap::valuetrue,则 和 的分配器ab应使用对 non-member 的无条件调用来交换swap否则,它们不应被交换,并且行为未定义,除非`a.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++ 没有“模式”。

于 2014-05-20T08:52:55.763 回答