12.8/32 のために が余分なreturn std::move(foo);
場合:move
コピー操作の省略の基準が満たされているか、ソース オブジェクトが関数パラメーターであり、コピーされるオブジェクトが左辺値によって指定されているという事実を除いて満たされる場合、コピーのコンストラクターを選択するためのオーバーロードの解決は次のとおりです。オブジェクトが右辺値によって指定されたかのように最初に実行されます。
return foo;
NRVO のケースであるため、コピーの省略が許可されます。foo
左辺値です。foo
したがって、からの戻り値への「コピー」用に選択されたコンストラクターは、meh
存在する場合は移動コンストラクターである必要があります。
ただし、追加には潜在的な効果があります。NRVO の資格がないmove
ため、移動が省略されるのを防ぎます。return std::move(foo);
私の知る限り、12.8/32 は、左辺値からのコピーを移動に置き換えることができる唯一の条件を示しています。コンパイラーは、一般に、コピー後に左辺値が使用されていないことを検出し (たとえば、DFA を使用して)、独自のイニシアチブで変更を行うことは許可されていません。ここでは、この 2 つの間に観察可能な違いがあると想定しています。観察可能な動作が同じである場合は、"as-if" ルールが適用されます。
したがって、タイトルの質問に答えるには、std::move
移動させたいときに戻り値を使用しますが、とにかく移動しません。あれは:
- あなたはそれを動かしたい、そして
- それは左辺値であり、
- コピー省略の対象外であり、かつ
- 値渡しの関数パラメーターの名前ではありません。
これは非常に手間がかかり、移動は通常安価であることを考えると、非テンプレート コードではこれを少し単純化できると言うことができます。次の場合に使用std::move
します。
- あなたはそれを動かしたい、そして
- それは左辺値であり、
- 気にしても仕方ありません。
単純化されたルールに従うことで、いくつかの移動省略を犠牲にします。そのようなタイプのstd::vector
移動は安価であり、おそらく気付かないでしょう (そして、気付いたとしても最適化できます)。移動するのにコストがかかるようなタイプstd::array
や、移動が安いかどうかわからないテンプレートの場合は、それについて心配するのが面倒になる可能性が高くなります。