【问题标题】:Why are the swap member functions in STL containers not declared noexcept?为什么 STL 容器中的交换成员函数没有声明为 noexcept?
【发布时间】:2014-07-08 09:15:45
【问题描述】:

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

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

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

【问题讨论】:

  • 我猜他们可能错过了。
  • 您使用的是哪个 C++ 库?
  • @MatsPetersson 我只是在看简单的标准,而不是特定的实现。
  • 这可能会有所帮助:link
  • @ForEveR:我将其复制到一个答案中,以便它正式存在于本问答中。

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


【解决方案1】:

除了what refp said,这是std-discussion 邮件列表中 Daniel Krügler 的帖子:

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

中解释

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

使用该论文中使用的术语,std::vector 的交换函数 有一个收缩契约,即它有关于以下方面的先决条件 参与对象的分配器。这意味着,存在 调用者可能违反先决条件和 应该允许实施表明我的不同方式 比终止。因此这样的函数不应该是noexcept, 但它应该有一个有效的元素“Throws: Nothing”,因为这 适用于前提条件满足的情况。

(link)

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

【讨论】:

  • 如果调用者违反了先决条件,那不就是一个普通的错误吗?如果调用者假定swap() 函数不能抛出,但无论如何它都会抛出(因为违反了先决条件),那么再见异常安全并保留不变量。程序也可以terminate()
  • @RalphTandetzky:是的,实现可以做到这一点。不过,标准是对此类程序提出no 要求。没有要求。没有。
【解决方案2】:

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


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

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

属于ab 的任何ComparePredHash 对象应 可交换,并应通过对非会员的无条件调用来交换 swap.

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

注意斜体由我添加。


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

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


该标准对未定义的行为做了以下说明:

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

本国际标准未强加任何要求的行为。


只有犯罪分子,也许还有推销员,才会认为 No 不是 No,但是当标准说 “没有要求”时 em> 真正的意思是没有要求”;将相关的 swap 函数标记为 noexcept 将对实现提出要求,而应该没有。


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

Alisdair MeredithJohn Lakos 就此事发表了一篇有趣的论文 (N3248),标题为“noexcept 阻止图书馆验证 ”。

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

如果 C++ 有一个标准化的“测试”与“生产”模式(如论文所称),noexcept 将有条件地适用,那么问题就会少得多.. 但因为它目前站着; C++ 没有“模式”。

【讨论】:

猜你喜欢
  • 2016-04-10
  • 2021-01-02
  • 2014-04-02
  • 1970-01-01
  • 2010-12-11
  • 2016-11-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多