如何在赋值运算符中使用noexcept与copy-and-swap惯用法?

liz*_*isk 16 c++ noexcept copy-and-swap c++11

移动赋值运算符通常应声明为noexcept(即将类型存储在STL容器中).但是复制和交换习惯用法允许在一段代码中定义复制和移动赋值运算符.在这种情况下如何处理noexcept说明符?复制结构可以抛出,但我怀疑它是否可以违反noexcept说明符.

// Is it correct considering that T copy constructor can throw?
T& operator=(T other) noexcept;
Run Code Online (Sandbox Code Playgroud)

Dan*_*rey 11

由于副本是呼叫的呼叫者进行的,因此它不是您的功能的一部分.因此,它不能由您的功能控制,因此,您不能在noexcept规范中包含此信息.

您唯一能做的就是安全地使用它并为您的规范添加两个选项noexcept.当然,这意味着你会得到一些假阴性.


Cas*_*eri 7

像往常一样,丹尼尔弗雷正确的.我想要的只是显示一段代码来说明这一点.

#include <iostream>

struct foo {

    foo() = default;

    foo(const foo&) {
        std::cout << "throw\n";
        throw 1;
    }

    foo& operator =(foo) noexcept {
        return *this;
    }
};

int main() {

    foo f, g;
    try {
        f = g; // throws
    }
    catch(int) {
        std::cout << "catch\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

使用gcc 4.8.1(-std=c++11 -Wall -Wextra -pedantic)编译时,它不会发出警告.运行代码会产生以下输出:

throw
catch
Run Code Online (Sandbox Code Playgroud)

因此,复制构造函数在调用时会抛出,但是内部没有考虑operator =(),因此,noexcept承诺得以实现.否则,catch在打印之前将调用terminate .