2011-07-20 17 views
4

私はこのコードがC++ 0xで合法であるかどうか不思議です。具体的には、関数move_it()で宣言されたオブジェクトは、main()で宣言されたオブジェクトに適切に移動されますか?このコードは合法ですか? (C++ 0xセマンティクスの移動)

#include <iostream> 
#include <string> 
#include <tr1/memory> 
using namespace std; 

class x 
{ 
public: 
    x() { cout << "create " << this << endl; } 
    ~x() { cout << "destroy " << this << endl; } 
}; 

x&& move_it() 
{ 
    x r; 
    return move(r); 
} 

int main() 
{ 
    x n = move_it(); 
    return 0; 
} 
+1

コンパイルしてみましたか?エラーがありましたか?ここの問題は何ですか? – Neal

+0

関数からローカルオブジェクトへの参照(任意の参照)を返す際に常にエラーが出るだけでなく、関数からの値の参照を返すことは意味がありません(static_castやstd :: moveの場合を除く)。 –

答えて

8

いいえ、左辺値参照と同様に、ローカルオブジェクトへの参照を返しています。

ちょうどそれを値で返し、xの想定される移動コンストラクタがrvalueを受け取るようにします。値によって返される場合、返されるオブジェクトはrvalueです。

あなたがラッキーな場合は、NRVOの最適化が(前と同じように)実行され、とにかくコピーが消去されます。

3

あなたはmainでアクセス未定義の動作を呼び出すmove_itからぶら下がっ右辺値参照を、戻ってきています。

あなたは、オブジェクトを移動xに戻り値の型を変更し、移動を取り除くしたい場合:

x move_it() 
{ 
    x r; 
    return r; 
} 

を(関数から戻ったときの自動変数は暗黙のうちに右辺値として扱われます。)

+0

@Flame:あなたが何を意味するかわからない。私はあなたが 'return x;'と 'x'がローカル変数であると言うとき、コンパイラは左辺値であれば左辺値' x'を扱います。明示的に「移動」する必要はありません。 – fredoverflow

+0

@Flame:いいえ、 'r'は左辺ですが、コンパイラは最初にコピーを削除しようとします。失敗した場合は、コピーを元に戻します。 –

+0

@Flame: 'move_it()'は 'x'を返す場合は* prvalue *、' x &&'を返す場合は* xvalue *です。 prvaluesとxvaluesはいずれも右辺値です。しかし、これは、返された自動変数をrvaluesのように扱うコンパイラとは関係ありません。 – fredoverflow

1

一般的に、テンプレートライブラリを実装していない人は、移動コンストラクタを実装して割り当てを移動するだけで、r値参照を使用する必要があります。

http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-9-of-n

+1

実際には、移動や割り当てのためにデフォルトが正しいことがよくありますが、他の機能については、必要な場合があります。実際に 'テンプレート ... foo(T &&)'が最も一般的なケースです。 –

関連する問題