2013-01-16 7 views
10

Artimaの記事C++の値のリファレンス(http://www.artima.com/cppsource/rvalue.html)には単語があります:そのため、基底クラスに渡すときにxだけでなくmove(x)と言う必要があります。これは、誤って名前付き変数から2回移動するのを防ぐように設計された移動セマンティクスの重要な安全機能です。Rvalue reference:rvaluesは暗黙的に移動されないのはなぜですか?

このようなダブルムーブができるとは思えません。あなたはこれの例を挙げることができますか?言い換えれば、T&&のすべてのメンバが参照のみでなく参照値になる場合はどうなりますか?

答えて

16

は、このシナリオを考えてみましょう:

void foo(std::string x) {} 
void bar(std::string y) {} 

void test(std::string&& str) 
{ 
    // to be determined 
} 

は、我々は両方とも同じ値で、strbar、その後、strfooを呼びたいです。これを行うための最善の方法は次のとおりですのでstrの値が指定されていない最初の移動後

foo(std::move(str)); // move str to x 
bar(std::move(str)); // move str to y...er, except now it's empty 

foo(str); // copy str to x 
bar(std::move(str)); // move str to y; we move it because we're done with it 

はこれを行うには間違いだろう。

したがって、右辺値参照の設計では、この暗黙的な移動はありません。その場合は、最初のstrの言及がstd::move(str)になるため、上記の最善の方法は機能しません。

3

私はそれを見る方法がある、我々はいくつかの右辺値参照のX持っていた場合:

T&& x = ...; 

を、私たちは、パラメータとしてXを使用して、いくつかの関数を呼び出した:我々は、Fを伝えるために何らかの方法必要

f(x) 

xに損害を与える可能性があるかどうか(または「xの所有権を取る」または「xを使用する最後のクライアントです」)。これを設計する

一つの方法は、すべての呼び出しを修飾するために、次のようになります。

f(yours_now(x)) // ok to damage 
f(still_mine(x)) // dont damage 

と修飾されていないコールを違法にします。

もう一つの方法は、一方通行のデフォルトを作るために次のようになります。

次のいずれかの私たちは、すべての利用予選同意する場合

f(yours_now(x)) // ok to damage 
f(x) // dont damage 

または

f(x) // ok to damage 
f(still_mine(x)) // dont damage 

もそうかさばるであり、我々はデフォルトで設定される必要があり一方的に、これは最高ですか?両方のケースで誤ってデフォルトを選択するコストを見てみましょう:

最初のケースではダメージは問題ありませんでしたが、間違っていました。この場合、不必要なコピーが作成されたためパフォーマンスは低下しますが、それ以外は大きな問題はありません。

2番目のケースでは、オブジェクトにダメージを与えることは問題ではありませんでしたが、誤ってそれを言っていました。これは、xが破損した状態になっているので、プログラムで論理バグを検出するのが困難になる可能性があります。

最初のケースは、その「安全な」ために選ばれたケースです。

関連する問題