[解決済み] 関数の戻り値に対して std::move を使用するのはいつですか?重複
質問
この場合
struct Foo {};
Foo meh() {
return std::move(Foo());
}
移動が不要なのは確かで、新しく作られた
Foo
はxvalueになるからです。
しかし、このような場合はどうでしょうか?
struct Foo {};
Foo meh() {
Foo foo;
//do something, but knowing that foo can safely be disposed of
//but does the compiler necessarily know it?
//we may have references/pointers to foo. how could the compiler know?
return std::move(foo); //so here the move is needed, right?
}
そこに移動が必要なのでしょう?
どのように解決するのですか?
の場合
return std::move(foo);
は
move
は12.8/32のため不要です。
コピー操作のエリシオンの基準が満たされている、または満たされているであろうとき コピー元のオブジェクトが関数のパラメータであるという事実を除けば、コピー操作のエリジオンの基準が満たされているか、または満たされている場合。 コピーされるオブジェクトがl値で指定されている場合、コピー用のコンストラクタを選択するためにオーバーロード コピーするコンストラクタを選択するためのオーバーロードの解決は、オブジェクトが rvalue で指定されている場合と同様に最初に実行されます。 オブジェクトがr値で指定されている場合と同じです。
return foo;
はNRVOの場合なので、コピーエリジョンが許可されています。
foo
は lvalue です。ですから、コンストラクタで選択された "copy" から
foo
の戻り値への
meh
は、もし存在するならば、移動コンストラクタであることが要求されます。
追加する
move
を追加することは、潜在的な効果がありますが、それは、移動がエリッドされるのを防ぐことです。
return std::move(foo);
は
ではない
NRVOの対象外です。
私の知る限り、12.8/32は、以下のように定めています。 だけ を規定しています。コンパイラは一般に、コピー後に lvalue が未使用であることを検出し (例えば DFA を使用して)、自分自身の判断で変更を加えることは許可されていません。私はここで、この 2 つの間に観察可能な違いがあると仮定しています。観察可能な動作が同じであれば、"as-if" 規則が適用されます。
というわけで、タイトルの質問に答えるために
std::move
を返り値に使うと、移動させたいときに、どうせ移動されないだろうから。ということです。
- 移動してほしいとき、そして
- はlvalueであり
- はコピー消去の対象外であり
- 値による関数パラメータの名前ではありません。
これを考慮すると、かなり手間がかかり、移動は
通常
であることを考えると、テンプレート以外のコードでは、これを少し単純化することができると言うのがいいかもしれません。使用方法
std::move
のときに
- 移動させたい
- はlvalueであり
- であり、それを気にすることはできません。
簡略化されたルールに従うことで、いくつかの手の消去を犠牲にすることになります。以下のようなタイプでは
std::vector
のような、移動が安価なタイプでは、おそらく気づくことはないでしょう (そして気づいたとしても最適化することができます)。のようなタイプでは
std::array
のようなタイプ、または移動が安価であるかどうか見当もつかないテンプレートでは、それを気にする可能性が高くなります。
関連
-
[解決済み】coutはstdのメンバではない
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み] static_cast, dynamic_cast, const_cast, reinterpret_cast はいつ使うべきですか?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] C++でクラスと構造体はいつ使い分けるべきか?
-
[解決済み] std::move()とは何ですか?また、どのような場合に使用するのですか?
-
[解決済み] CとC++でmain()は何を返すべきですか?
-
[解決済み] noexceptを本当に使うべきはいつですか?
-
[解決済み] C++11 rvalues と移動セマンティクスの混乱(return 文)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】C-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み] 配列のベクトルを扱う正しい方法
-
[解決済み] sprintfのようなstd::stringの書式設定
-
[解決済み] c++11 戻り値の最適化か移動か?重複