为什么STL容器中的交换成员函数没有声明为noexcept ?
Why are the swap member functions in STL containers not declared noexcept?
从N3797开始,c++标准要求容器的swap
函数不抛出任何异常,除非另有规定[container.requirements.general]
(23.2.1§10)。
- 为什么指定不抛出的
swap
成员函数没有声明为noexcept
?
同样的问题也适用于特殊的非成员swap
重载。
进一步说明refp所说的,这里是Daniel krstd-discussion
邮件列表上的一篇文章:
将函数声明为无条件noexcept的内部策略是
说明http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3279.pdf用那篇论文中使用的术语,std::vector的交换函数有一个缩小的合同,它有先决条件吗参与对象的分配器。这意味着存在调用者违反前提条件的可能性应该允许实现以不同的方式发出信号而不是终止。因此,这些功能不应该是不例外的,但它应该有一个有效的元素"抛出:无",因为这用于满足前提条件的情况。
(链接)
上述内部政策是对你的问题的规范的官方回答。
乍听起来可能很奇怪,但没有明确声明标准容器的swap
是noexcept
是有意的;这一切都归结为未定义行为 (UB)。
23.2.1p9
集装箱通用要求[container.requirements.general]
表达式
a.swap(b)
,用于标准容器a
和b
array
以外的容器类型,应交换a
的值和b
不调用任何移动、复制或交换操作单个容器元素。任何属于
a
和b
的Compare
、Pred
或Hash
对象可互换,可通过无条件呼叫非会员进行交换swap
.如果
allocator_traits<allocator_type>::propagate_on_container_swap::value
是true
,那么a
和b
的分配器也要交换使用非限定调用非成员swap
。否则,他们应当不被交换,并且行为是未定义的,除非` .get_allocator . `() == b.get_allocator ().
<一口> 注意: 斜体添加我。一口>
为什么上一节与我的问题相关?
由于标准容器的swap
有一个前提条件(最重要的是前面引用的标准部分的最后一段),如果不满足,可能会导致UB,标准不想对实现施加"不可能"的约束。
标准对未定义行为有如下规定:
1.3.24
未定义行为[defns.undefined]
本国际标准没有要求的行为。
只有罪犯,也许还有推销员,才会认为No不是No,但是当标准说"无要求"时,它实际上是指"无要求";将相关的swap
函数标记为noexcept
将对实现施加要求,而本应没有。
为什么标准不想强加这样的要求?
关于这个问题,Alisdair Meredith和John Lakos发表了一篇有趣的论文(N3248),题为" noexcept
阻止库验证"。
简而言之,它讨论了noexcept
如何阻止库实现在库代码中使用asserts
(即。标准库的实现),甚至在调试模式中,以及它的含义。
如果c++有一个标准化的"测试"与"生产"模式(如论文所称),其中noexcept
将有条件地应用,这将会少得多的问题。但就目前的情况来看;c++没有"modes"
- .cpp和.h文件中的模板专用化声明
- 未在作用域中声明unordered_map
- C++避免重复声明的语法是什么
- 如何确保C++函数在定义之前声明(如override关键字)
- 错误:未在此范围内声明'reverse'
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 为什么在定义函数之前先声明它
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 如何声明包装器类型 X 的移动构造函数<T> noexcept 取决于is_nothrow_move_constructible<T>?
- 如何声明 noexcept 如果只有属性的成员函数是 noexcept
- 我应该声明我的异常的副本构造函数noexcept吗
- C++11,“noexcept”说明符,定义与声明
- 为什么 noexcept 说明符的作用域不在声明的方法内?
- 为什么std::map find()没有声明为noexcept
- 为什么std::vector使用move构造函数,尽管声明为noexcept(false)
- g++-4.8.1认为没有异常说明的显式声明的析构函数总是noexcept(true)
- 正在转换到C++11,其中析构函数是用noexcept隐式声明的
- 理论上而不是实践上的投掷函数应该被声明为noexcept
- 为什么STL容器中的交换成员函数没有声明为noexcept ?
- c++ noexcept声明改变了模板演绎