为什么STL容器中的交换成员函数没有声明为noexcept? 标准的C++要求容器的代码>交换< /代码>函数不抛出任何异常,除非指定否则 [容器。要求。一般] < /代码>(23.2.1节10)。

为什么STL容器中的交换成员函数没有声明为noexcept? 标准的C++要求容器的代码>交换< /代码>函数不抛出任何异常,除非指定否则 [容器。要求。一般] < /代码>(23.2.1节10)。,c++,c++11,swap,noexcept,C++,C++11,Swap,Noexcept,为什么指定为不抛出的swap成员函数未声明noexcept 同样的问题也适用于专门的非成员交换重载 一开始听起来可能有些奇怪,但没有明确说明标准容器的swap是noexcept是故意的;这一切归结为未定义的行为(UB) 23.2.1p9一般集装箱要求[Container.Requirements.General] 用于标准容器a和b的表达式a.swap(b) 除数组以外的容器类型应交换a 和b,而不调用服务器上的任何移动、复制或交换操作 单个容器元素 属于a和b的任何Compare、Pred

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

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

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


23.2.1p9
一般集装箱要求
[Container.Requirements.General]

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

属于
a
b
的任何
Compare
Pred
Hash
对象都应 可交换,且应通过非会员的非限定呼叫进行交换
交换

如果 Alisdair Meredith和John Lakos在这件事上发表了名为“
noexcept
阻止库验证”的文章

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

<如果C++有一个标准化的“测试”和“生产”模式(如本文所称的那样),在代码> >除了< /代码>有条件地应用,这将远没有问题。但就目前情况而言;C++没有“模式”。

另外,这里有一个来自Daniel Kr U.GLER的关于<代码> STD讨论< /代码>邮件列表:

的帖子。 将函数声明为无条件noexcept的内部策略是 解释

使用本文中使用的术语,std::vector的swap函数 有一个缩小的合同,就是它有关于 参与对象的分配器。这意味着,存在 呼叫者可能违反先决条件和 应该允许实现以我不同的方式发出这一信号 而不是通过终止。因此,这些功能也不例外, 但它应该有一个有效的元素“抛出:没有”,因为 适用于满足前提条件的情况

()


内部策略是对你的问题的规范的、官方的回答。我猜他们可能错过了。你在使用哪一个C++库?@ MatsPutsson我只是在看裸露的标准,而不是一个特定的实现。这可以帮助:“永远”:我把它复制成答案,因此,它正式存在于本问答中。为什么将分配器与数据一起交换会有问题?这是对UB定义的一个有趣的理解。不要说这是错的。@GreenScape我会把你的评论/问题放到一个新的问答中,有问题的时候我会打电话给你。@GreenScape这应该能回答你的问题:如果打电话的人违反了先决条件,这不是一个普通的错误吗?如果调用者假定

swap()
函数不能抛出,但它仍然抛出(因为违反了先决条件),那么再见异常安全和保留不变量。程序也可以
terminate()
@RalphTandetzky:是的,实现可以做到这一点。不过,标准是对这样的计划不作任何要求。没有要求。没有一个