簡単な答えは、通常の参照コードと同じように右辺値参照のコードを記述し、99%の時間でそれらを同じように扱う必要があるということです。これには、参照を返すことに関するすべての古いルールが含まれます(つまり、ローカル変数への参照を返すことはありません)。
std :: forwardを利用し、左辺値または右辺値参照のいずれかを取る汎用関数を記述できるテンプレートコンテナクラスを作成している場合を除き、これは多かれ少なかれ当てはまります。
moveコンストラクターとmove割り当ての大きな利点の1つは、それらを定義すると、RVO(戻り値の最適化)とNRVO(名前付き戻り値の最適化)が呼び出されなかった場合にコンパイラーがそれらを使用できることです。これは、コンテナや文字列などの高価なオブジェクトを、メソッドから効率的に値で返すには非常に巨大です。
ここで、右辺値参照で興味深い点は、通常の関数への引数としても使用できることです。これにより、const参照(const foo&other)とrvalue参照(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);