簡単な答えは、通常の参照コードと同じように右辺値参照のコードを記述し、99% の時間、精神的に同じように扱う必要があるということです。これには、参照を返すことに関するすべての古い規則が含まれます (つまり、ローカル変数への参照を決して返さない)。
std::forward を利用する必要があり、左辺値または右辺値参照のいずれかを取る汎用関数を記述できる必要があるテンプレート コンテナ クラスを記述していない限り、これは多かれ少なかれ真実です。
移動コンストラクターと移動代入の大きな利点の 1 つは、それらを定義すると、RVO (戻り値の最適化) と NRVO (名前付きの戻り値の最適化) の呼び出しに失敗した場合に、コンパイラーがそれらを使用できることです。これは、コンテナや文字列などの高価なオブジェクトをメソッドから効率的に値で返すにはかなり大きいです。
右辺値参照で興味深い点は、それらを通常の関数の引数としても使用できることです。これにより、const 参照 (const foo& other) と右辺値参照 (foo&& other) の両方のオーバーロードを持つコンテナーを作成できます。単なるコンストラクター呼び出しで引数を渡すには扱いにくい場合でも、それを行うことができます。
std::vector vec;
for(int x=0; x<10; ++x)
{
// automatically uses rvalue reference constructor if available
// because MyCheapType is an unamed temporary variable
vec.push_back(MyCheapType(0.f));
}
std::vector vec;
for(int x=0; x<10; ++x)
{
MyExpensiveType temp(1.0, 3.0);
temp.initSomeOtherFields(malloc(5000));
// old way, passed via const reference, expensive copy
vec.push_back(temp);
// new way, passed via rvalue reference, cheap move
// just don't use temp again, not difficult in a loop like this though . . .
vec.push_back(std::move(temp));
}
STL コンテナは更新され、ほぼすべてのもの (ハッシュ キーと値、ベクトルの挿入など) のオーバーロードを移動できるようになりました。これらが最も多く見られる場所です。
それらを通常の関数に使用することもできます。右辺値参照引数のみを指定すると、呼び出し元にオブジェクトを作成させ、関数に移動させることができます。これは単なる例にすぎませんが、私のレンダリング ライブラリでは、読み込まれたすべてのリソースに文字列を割り当てて、デバッガーで各オブジェクトが何を表しているかを簡単に確認できるようにしています。インターフェイスは次のようなものです。
TextureHandle CreateTexture(int width, int height, ETextureFormat fmt, string&& friendlyName)
{
std::unique_ptr<TextureObject> tex = D3DCreateTexture(width, height, fmt);
tex->friendlyName = std::move(friendlyName);
return tex;
}
これは「漏れやすい抽象化」の形式ですが、ほとんどの場合、すでに文字列を作成しなければならなかったという事実を利用して、さらに別のコピーを作成することを避けることができます。これは正確には高性能なコードではありませんが、人々がこの機能に慣れるにつれて可能性を示す良い例です。このコードでは、変数が呼び出しに対して一時的であるか、std::move が呼び出される必要があります。
// move from temporary
TextureHandle htex = CreateTexture(128, 128, A8R8G8B8, string("Checkerboard"));
また
// explicit move (not going to use the variable 'str' after the create call)
string str("Checkerboard");
TextureHandle htex = CreateTexture(128, 128, A8R8G8B8, std::move(str));
また
// explicitly make a copy and pass the temporary of the copy down
// since we need to use str again for some reason
string str("Checkerboard");
TextureHandle htex = CreateTexture(128, 128, A8R8G8B8, string(str));
しかし、これはコンパイルされません!
string str("Checkerboard");
TextureHandle htex = CreateTexture(128, 128, A8R8G8B8, str);