13

このプログラム:

#include <iostream>
struct T {
    T() {}
    T(const T &) { std::cout << "copy constructor "; }
    T(T &&) { std::cout << "move constructor "; }
};
int main() {
    ([](T t) -> T { return t; })({}); std::cout << '\n';
    ([](T t) -> T { return void(), t; })({}); std::cout << '\n';
    ([](T t) -> T { return void(), std::move(t); })({}); std::cout << '\n';
}

gcc-4.7.1出力(リンク)でコンパイルした場合:

move constructor 
copy constructor 
move constructor 

なぜコンマ演算子がこの効果をもたらすのですか?標準は言う:

5.18コンマ演算子[expr.comma]

1-[...]結果のタイプと値は、右のオペランドのタイプと値です。結果は、右のオペランド[...]と同じ値のカテゴリになります。右のオペランドの値が一時的なものである場合、結果はその一時的なものになります。

コンマ演算子がプログラムのセマンティクスに影響を与えることを可能にする何かを見逃したことがありますか、それともこれはgccのバグですか?

4

2 に答える 2

14

自動移動は、コピーの省略の適格性に基づいています。

§12.8 [class.copy] p32

ソースオブジェクトが関数パラメーターであり、コピーされるオブジェクトが左辺値で指定されていることを除いて、コピー操作の省略基準が満たされている、または満たされる場合、コピーのコンストラクターを選択するためのオーバーロード解決は次のようになります。最初は、オブジェクトが右辺値で指定されているかのように実行されます。[...]

また、戻り式が自動オブジェクトの名前である場合は、コピーの省略が許可されます。

§12.8 [class.copy] p31

returnクラス戻り型を持つ関数のステートメントで、式が関数戻り型と同じcv-unqualified型を持つ不揮発性自動オブジェクト(関数またはcatch-clauseパラメーター以外)の名前である場合、自動オブジェクトを関数の戻り値に直接構築することにより、コピー/移動操作を省略できます。

コンマ演算子を挿入すると、式は自動オブジェクトの名前ではなく、コピーの省略を抑制するオブジェクトへの参照になります。

于 2012-09-05T19:20:37.000 に答える
8

t ローカルの名前付き変数であり、したがって左辺値です。コンマ演算子は、文書化されているとおりに動作します。

むしろ、なぜ右辺値参照にバインドreturn t;できるのかを尋ねる必要があります-それが本当の魔法です。t

于 2012-09-05T19:19:40.120 に答える