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

时间:2013-09-17 11:07:40

标签: c++ c++11 noexcept copy-and-swap

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

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

2 个答案:

答案 0 :(得分:11)

由于副本在调用者的方上,因此它不是您的函数所做的一部分。因此,它不能由您的函数控制,因此,您不能在noexcept规范中包含此信息。

您唯一能做的就是安全地播放并将两个选项添加到noexcept规范中。当然,这意味着你会得到一些假阴性。

答案 1 :(得分:7)

像往常一样,Daniel Freycorrect。我想要的只是显示一段代码来说明这一点。

#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";
    }
}

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

throw
catch

因此,复制构造函数在调用时会抛出,但在operator =()内没有考虑,因此noexcept承诺已经完成。否则,将在打印catch之前调用terminate。