65

重複の可能性:
移動セマンティクスとは?

最近、C++11 のセミナーに参加したところ、次のちょっとしたアドバイスがありました。

when you have && and you are unsure, you will almost always use std::move

std::moveいくつかの代替手段や使用すべきではない場合とは対照的に、なぜ使用する必要があるのか​​ を誰かに説明してもらえますstd::moveか?

4

4 に答える 4

97

まず、私が対処する質問にはおそらく誤解があります:コードで
見るときはいつでもT&& t(そして T はテンプレート型ではなく実際の型です)、の値カテゴリはt右辺値ではなく左辺値 (参照) であることに注意してください。 (仮)もう。とても紛らわしいです。はT&&単に右辺値1であったオブジェクトから構築さtれることを意味しますが、それ自体は右辺値ではなく左辺値です。名前がある場合 (この場合は)、左辺値であり、自動的に移動しませんが、名前がない場合 ( の結果) は右辺値であり、可能であれば結果に自動的に移動します。タイプ(この場合t t3+4T&&) は、変数 (この場合は左辺値) の値カテゴリとはほとんど関係がありません。

そうは言ってもT&& t、コードに記述した場合、それは一時的な変数への参照があることを意味し、必要に応じて破棄してもかまいません。変数に複数回アクセスする必要がある場合は、アクセスしたくありませんstd::move。そうしないと、値が失われます。しかし、最後にアクセスしたときは、必要に応じて別のユーザーtにとって安全です。(そして 95% の確率で、それがあなたのやりたいことです)。これはすべて変数にも当てはまり ます。std::moveTauto&&

1. ifTはテンプレート タイプでT&&あり、代わりに転送参照です。この場合、前回のstd::forward<T>(t)代わりに使用します。この質問std::move(t)を参照してください。

于 2013-01-23T18:26:19.583 に答える
30

この記事は、一般的な右辺値参照の主題についてかなり啓発的であることがわかりました。彼は最後に言及std::moveします。これはおそらく最も関連性の高い引用です。

std::move, from <utility>--を使用する必要があります。std::moveこれは、「正直に言うと、左辺値があることは知っていますが、右辺値にしたい」という言い方です。std::moveそれ自体は何も動かしません。左辺値を右辺値に変換するだけなので、移動コンストラクターを呼び出すことができます。


次のような移動コンストラクタがあるとします。

MyClass::MyClass(MyClass&& other): myMember(other.myMember)
{
    // Whatever else.
}

statement を使用するとother.myMember、返される値は左辺値です。したがって、コードはコピーコンストラクターを使用して初期化しますthis->myMember。しかし、これはムーブ コンストラクターであるため、一時オブジェクトであることがわかり、otherそのメンバーも同様です。したがって、より効率的なmoveコンストラクターを使用して初期化したいのですthis->myMember。を使用std::moveすると、コンパイラがother.myMember右辺値参照のように処理し、必要に応じてムーブ コンストラクターを呼び出すようになります。

MyClass::MyClass(MyClass&& other): myMember(std::move(other.myMember))
{
    // Whatever else.
}

保持する必要があるオブジェクトには使用しないstd::moveでください。移動コンストラクターは、渡されたオブジェクトを台無しにすることがほぼ保証されています。そのため、一時的にのみ使用されます。

それが役立つことを願っています!

于 2013-01-23T18:34:16.833 に答える
4

type T&&、右辺値のオブジェクトがある場合、後でその内部状態に依存する人がいないため、このオブジェクトを安全に移動できることを意味します。

移動はコピーよりもコストがかかることはないため、ほとんどの場合、移動する必要があります。そして、それを移動するには、std::move関数を使用する必要があります。

std::move安全であっても、いつ避けるべきですか? 些細な例では使用しません。たとえば、次のようになります。

 int x = 0;
 int y = std::move(x);

それに加えて、欠点は見当たりません。コードが複雑にならない場合は、可能な限り移動を行う必要があります。

移動したくない別の例は、戻り値です。言語は、戻り値が (少なくとも) 移動されることを保証するため、次のように記述しないでください。

return std::move(x); // not recommended

(運が良ければ、戻り値の最適化がヒットします。これは、移動操作よりも優れています。)

于 2013-01-23T18:18:26.710 に答える
2

コピーを行わずに、オブジェクトのコンテンツを別の場所に「転送」する必要がある場合は、move を使用できます。std::move を使用すると、コピーを行わずにオブジェクトが一時オブジェクトのコンテンツを取得することもできます。

ウィキペディアからRvalue参照とムーブ コンストラクターの詳細を参照してください。

于 2013-01-23T18:09:55.023 に答える