次の構造体があるとします。
struct ABC
{
ABC(){cout << "ABC" << endl;}
~ABC() noexcept {cout << "~ABC" << endl;}
ABC(ABC const&) {cout << "copy" << endl;}
ABC(ABC&&) noexcept {cout << "move" << endl;}
ABC& operator=(ABC const&){cout << "copy=" << endl;}
ABC& operator=(ABC&&) noexcept {cout << "move=" << endl;}
};
次の出力:
std::pair<std::string, ABC> myPair{{}, {}};
は:
ABC
copy
~ABC
~ABC
次の出力中:
std::pair<std::string, ABC> myPair{{}, ABC{}};
は:
ABC
move
~ABC
~ABC
2つの違いを理解しようとして、最初のケースはコピーリスト初期化を使用しているのに対し、2番目のケースは名前のない一時的な直接リスト初期化を使用していることを特定したと思います(ここではそれぞれ7番と2番) : http://en.cppreference.com/w/cpp/language/list_initialization )。
同様の質問を検索すると、これが見つかりました:なぜ標準は直接リストの初期化とコピーリストの初期化を区別するのですか? そしてこれ:コピーリストの初期化は概念的にコピーctorを呼び出しますか?.
これらの質問に対する回答では、コピー リストの初期化の場合、明示的なコンストラクターを使用するとコードの形式が崩れるという事実について説明しています。実際、ABC のデフォルト コンストラクターを明示的にすると、最初の例はコンパイルされませんが、それは (おそらく) 別の問題です。
では、問題は次のとおりです。最初のケースでは一時的にコピーされたのに、2 番目のケースでは移動されたのはなぜですか? copy-list-initialization の場合、移動を妨げているのは何ですか?
注意として、次のコード:
std::pair<std::string, ABC> myPair = std::make_pair<string, ABC>({}, {});
また、ABC のムーブ コンストラクターが呼び出されます (コピー コンストラクターは呼び出されません) が、別のメカニズムが関与する場合があります。
https://ideone.com/Kc8xInでコードを試すことができます (C++14 モードで gcc-4.9.2 を使用) 。