19

移動代入演算子は、多くの場合、noexcept として宣言する必要があります (つまり、型を STL コンテナーに格納するため)。しかし、copy-and-swap イディオムを使用すると、copy-代入演算子と move-代入演算子の両方を 1 つのコードで定義できます。この場合、noexcept 指定子をどうするか? コピー構造はスローできますが、noexcept 指定子に違反できるかどうかは疑問です。

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

2 に答える 2

13

コピーは呼び出し側で作成されるため、関数の動作の一部ではありません。したがって、関数で制御することはできません。したがって、この情報をnoexcept仕様に含めることはできません。

あなたができる唯一のことは、それを安全にプレイし、両方のオプションをnoexcept仕様に追加することです. もちろん、それはあなたがいくつかの偽陰性を得ていることを意味します.

于 2013-09-17T11:19:26.120 に答える
10

いつものように、Daniel Frey正しいです。私が望むのは、要点を説明するコードを表示することだけです。

#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約束は果たされました。そうしないと、terminate が出力される前に呼び出さcatchれます。

于 2013-09-17T15:06:08.310 に答える