4

R 値の参照がなければ、C++ での完全な転送は不可能であることを理解しています。

ただし、知りたいのですが、それらを必要とするものは他にありますか?


たとえば、このページでは、R 値の参照が明らかに必要な次の例を指摘しています。

  X foo();
  X x;
  // perhaps use x in various ways
  x = foo();

上記の最後の行:

  • が保持するリソースを破棄しますx
  • によって返された一時ファイルからリソースを複製しますfoo
  • 一時オブジェクトを破棄して、そのリソースを解放します。

swapただし、適切に実装されていれば、簡単な変更で問題が解決したように思えます。

X foo();
X x;
// perhaps use x in various ways
{
    X y = foo();
    swap(x, y);
}

したがって、この最適化にはr値参照は必要ないように思えます。(あれは正しいですか?)

では、r-value 参照では解決できなかったいくつかの問題は何ですか (私が既に知っている完全な転送を除く)?

4

1 に答える 1

12

では、r-value 参照では解決できなかったいくつかの問題は何ですか (私が既に知っている完全な転送を除く)?

はい。swapトリックが機能する (または少なくとも最適に機能する) ためには、構築時にクラスが空の状態になるように設計する必要があります。vector完全に空から始めるのではなく、常にいくつかの要素を予約する実装を想像してみてください。そのようなデフォルトで構築さvectorれたものから既存のvectorものと交換することは、(このvector実装のデフォルト コンストラクターで) 追加の割り当てを行うことを意味します。

実際の移動では、デフォルトで構築されたオブジェクトにデータが割り当てられている可能性がありますが、移動元のオブジェクトは割り当てられていない状態のままになる可能性があります。

また、次のコードを検討してください。

std::unique_ptr<T> make_unique(...) {return std::unique_ptr<T>(new T(...));}

std::unique_ptr<T> unique = make_unique();

これは、言語レベルの移動セマンティクスがなければ不可能です。なんで?2番目のステートメントのため。標準では、これはコピーの初期化です。その名前が示すように、型がcopyableである必要があります。そして、全体的なポイントunique_ptrは、それが、まあ、ユニークだということです. IE: コピー不可。

移動セマンティクスが存在しない場合は、それを返すことができませんでした。そうそう、コピー省略などについて話すことはできますが、覚えておいてください: 省略は最適化です。準拠するコンパイラは、コピー コンストラクターが存在し、呼び出し可能であることを引き続き検出する必要があります。コンパイラには、それを呼び出さないオプションがあります。

いいえ、移動セマンティクスを でエミュレートすることはできませんswap。率直に言って、できたとしても、なぜそうしたいのですか?

swap実装は自分で書く必要があります。したがって、6 つのメンバーを持つクラスがある場合、swap関数は各メンバーを順番に交換する必要があります。すべての基本クラスなども再帰的に。

C++11 (ただし、VC10 または VC2012 ではありません) では、コンパイラが移動コンストラクターを作成できます

はい、それなしで逃げることができる状況があります。しかし、それらは信じられないほどハックに見え、なぜそのようにしているのかを理解するのが難しく、何よりも重要なのは、読み手と書き手の両方にとって物事を困難にしています。

swapパフォーマンスのために、コードを読むのが面倒で、書くのが難しく、エラーが発生しやすくなるようなことをしたい場合 (たとえば、別のメンバーを関数に追加せずにクラスに追加するなど)、次のようにします。おそらく言語の一部になるはずのものを見ています。特に、コンパイラが非常に簡単に処理できるものである場合.

于 2012-06-23T07:27:46.520 に答える