gcc、 clang 、および VS2015 は、 object をスローした後、以下のコードの move コンストラクターへの呼び出しを省略しませんa
。§8.12[class.copy]/31 (N4140) の箇条書き (31.2) で確立された条件が満たされているように思えます。
#include <iostream>
struct A
{
A() { std::cout << "Default ctor " << '\n'; }
A(const A& a) { std::cout << "Copy ctor" << '\n'; }
A(A&& a) { std::cout << "Move ctor" << '\n'; }
~A() { std::cout << "Destructor " << '\n'; }
};
int main()
{
try
{
A a;
throw a;
}
catch(A& a) { std::cout << "Caught" << '\n'; }
}
は左辺値ですa
が、§12.8/32 に従って、オブジェクトが右辺値によって指定されているかのように、コピーのコンストラクターを選択するためのオーバーロード解決が最初に実行されます。つまり、move コンストラクターの呼び出しは問題ありません。上記のムーブ コンストラクターの定義を消去すると、コピー コンストラクターが呼び出されますが、省略されていません。
コピー省略が標準で義務付けられていないことは理解していますが、上記の 3 つのコンパイラがこの特定の例でこの最適化を回避しているという事実を正当化できる特別な条件があるかどうか知りたいです。
上記のリンクからの gcc の出力例:
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
デフォルトのセクター
移動先
デストラクタ
つかまった
デストラクタ