いいえ。ベスト プラクティスは直接return t;
です。
クラスT
に削除されていないムーブ コンストラクターがあり、noticeがコピー省略の対象とt
なるローカル変数である場合、ムーブは返されたオブジェクトを同様に構築します。ただし、エリジョンをコピー/移動する資格があるため、構築は省略できますが、常に移動コンストラクターを使用して戻り値を構築します。return t
return std::move(t);
return t;
return std::move(t)
クラス内のムーブ コンストラクターT
が削除されているが、コピー コンストラクターが使用可能な場合、return std::move(t);
コンパイルされませんが、コピー コンストラクターreturn t;
を使用してコンパイルされます。言及された@Kerrekとは異なりt
、右辺値参照にバインドされていません。コピー省略の対象となる戻り値には、2 段階のオーバーロード解決があります。最初に移動してからコピーを試してください。移動とコピーの両方が省略される可能性があります。
class T
{
public:
T () = default;
T (T&& t) = delete;
T (const T& t) = default;
};
T foo()
{
T t;
return t; // OK: copied, possibly elided
return std::move(t); // error: move constructor deleted
return static_cast<T&>(t); // OK: copied, never elided
}
式が左辺値であり、コピー省略の対象にならない場合return
(非ローカル変数または左辺値式を返す可能性が最も高い)、それでもコピーを避けたい場合は、std::move
が役立ちます。ただし、ベスト プラクティスは、コピーの省略を可能にすることです。
class T
{
public:
T () = default;
T (T&& t) = default;
T (const T& t) = default;
};
T bar(bool k)
{
T a, b;
return k ? a : b; // lvalue expression, copied
return std::move(k ? a : b); // moved
if (k)
return a; // moved, and possibly elided
else
return b; // moved, and possibly elided
}
標準の 12.8(32) では、このプロセスについて説明しています。
12.8 [class.copy]
32 コピー操作の省略の基準が満たされているか、ソース オブジェクトが関数パラメーターであり、コピーされるオブジェクトが左辺値によって指定されているという事実を除いて満たされる場合、コピーのコンストラクターを選択するためのオーバーロード解決オブジェクトが右辺値によって指定されたかのように最初に実行されます。オーバーロードの解決が失敗した場合、または選択されたコンストラクターの最初のパラメーターの型がオブジェクトの型 (おそらく cv 修飾) への右辺値参照ではない場合、オブジェクトを左辺値と見なしてオーバーロードの解決が再度実行されます。[ 注: この 2 段階のオーバーロード解決は、コピーの省略が発生するかどうかに関係なく実行する必要があります。省略が実行されない場合に呼び出されるコンストラクターを決定し、呼び出しが省略された場合でも、選択されたコンストラクターにアクセスできる必要があります。—終わりのメモ]