为什么basic_string :: swap不是noexcept?

nos*_*sid 21 c++ c++11

我刚刚发现basic_string的两个交换函数(命名空间std中的成员函数和函数)没有用noexcept声明- 既不是在GCC-4.8的标准库中也不是在最新的C++草案N3690中.

另一方面,移动构造函数以及移动赋值运算符使用noexcept声明.这表明应该可以提供noexcept交换功能.

问题:没有使用noexcept声明交换函数的原因是什么?

更新:问题是我想在我自己的交换函数中使用模板函数,它使用static_assert检查交换是否实际上是noexcept,例如:

struct foo {
    bar_t bar;
    baz_t baz;
    void swap(foo& rhs) noexcept {
        swap_noexcept(bar, rhs.bar);
        swap_noexcept(baz, rhs.baz);
    }
};
Run Code Online (Sandbox Code Playgroud)

但是,只有在使用noexcept声明交换函数时才有效,但情况并非如此basic_string.

And*_*owl 20

C++ 11标准的第21.4.6.8段规定:

21.4.6.8 basic_string::swap[string :: swap]

void swap(basic_string& s);
Run Code Online (Sandbox Code Playgroud)

1 后置条件:*它包含与s中相同的字符序列,s包含*this中相同的字符序列.

2 投掷:没什么.

3 复杂性:恒定时间.

因此,必须得出结论,缺席noexcept是疏忽.

关于assign()成员函数的第21.4.6.3段给出了另一条线索:

basic_string& assign(basic_string&& str) noexcept;
Run Code Online (Sandbox Code Playgroud)

效果:该函数*this用一个长度为字符串的字符串替换受字符串控制的字符串,str.size()其元素是受其控制的字符串的副本str.[ 注意:有效的实施是swap(str). - 结束说明]

3 返回:*this.

如果swap(str)被认为是一个有效的实施assign(),并assign()作为无条件标记noexcept,然后是有意义的假设swap()noexcept也.

  • “抛出:无”与当前标准中的 noexcept 不同。如果函数具有前提条件,并且调用违反了这些前提条件,则会导致未定义的行为,为此允许实现抛出异常。如果先决条件函数被声明为 noexcept,则该异常将导致 terminate() 而不是传播。但是, string::swap 没有列出任何先决条件,这意味着这看起来确实是个错误。我们需要检查分配器的传播交换规则来确定。 (2认同)
  • @Jeffrey Yasskin,当发生未定义的行为时,规范不容许它使`noexcept`函数抛出异常而不调用`std :: terminate()`吗? (2认同)