21

実際の C++ 標準では、次の規則を満たすコレクションを作成することは、不可能ではないにしても困難です。

  1. 例外安全性、
  2. 安価な内部操作 (実際の STL コンテナーでは、操作はコピーです)、
  3. 自動メモリ管理。

(1) を満たすために、コレクションは生のポインターを格納できません。(2) を満たすには、コレクションは生のポインターを格納する必要があります。(3) を満たすために、コレクションは値によってオブジェクトを格納する必要があります。

結論:3つの項目は互いに矛盾しています。

shared_ptrコレクションが要素を移動する必要がある場合、コンストラクタとデストラクタの 2 つの呼び出しを行う必要があるため、項目 (2) は s が使用されている場合には満たされません。のような大規模memcpy()なコピー/移動操作はできません。

unique_ptr説明されている問題はとによって解決されるというのは正しいstd::move()ですか? ツールを使用するコレクションは、次の 3 つの条件すべてを満たすことができます。

  1. 例外の副作用としてコレクションが削除されると、unique_ptrのデストラクタが呼び出されます。メモリリークなし。
    • unique_ptr参照カウンター用の余分なスペースは必要ありません。したがって、その本体は、ラップされたポインターとまったく同じサイズである必要があります。
    • よくわかりませんが、これにより、同様の操作(?unique_ptrsを使用してのグループを移動できるように見えますが、memmove()
    • それが不可能な場合でも、std::move()オペレーターはunique_ptr、コンストラクター/デストラクターのペアの呼び出しを行わずに各オブジェクトを移動できます。
  2. unique_ptr指定されたメモリの排他的所有権を持ちます。偶発的なメモリ リークは発生しません。

これは本当ですか?を使用するその他の利点は何unique_ptrですか?

4

5 に答える 5

6

私は完全に同意します。ヒープに割り当てられたオブジェクトを処理する自然な方法がついに登場しました。

への答え:

よくわかりませんが、これにより、同様の操作unique_ptrを使用して のグループを移動できるようです。memmove()

これを許可するという提案がありましたが、C++11 標準にはなっていません。

于 2009-06-05T16:31:36.853 に答える
2

はい、あなたは正しいです。r値参照のおかげでこれが可能になると付け加えるだけです。

于 2009-06-05T15:51:30.443 に答える
2

例外の副作用としてコレクションが削除されると、unique_ptr のデストラクタが呼び出されます。メモリリークなし。

はい、のコンテナはunique_ptrこれを満たします。

unique_ptr には、参照カウンター用の余分なスペースは必要ありません。したがって、その本体は、ラップされたポインターとまったく同じサイズである必要があります

unique_ptrのサイズは実装定義です。デフォルトのデストラクタを使用するすべての合理的な実装はunique_ptr、サイズがポインタにすぎない可能性がありますが、標準ではこれが保証されていません。

よくわかりませんが、memmove() のような操作 (?) を使用して、unique_ptrs のグループを移動できるようです。

絶対違う。unique_ptr自明なクラスではありません。したがって、それを回避することはできませんmemmove。たとえそうであったとしてもmemmove、オリジナルのデストラクタを呼び出す必要があるため、それらだけにすることはできません。の後に がmemmove続く必要がありmemsetます。

それが不可能な場合でも、std::move() 演算子を使用すると、コンストラクター/デストラクターのペアの呼び出しを行わずに、各 unique_ptr オブジェクトを移動できます。

また、不正解です。移動によって、コンストラクターとデストラクタが呼び出されなくなるわけではありません。破壊されているものは破壊unique_ptrする必要があります。デストラクタへの呼び出しが必要です。同様に、 newはコンストラクターを呼び出す必要があります。それがオブジェクトの寿命の始まりです。unique_ptr

それを避けることはできません。それがC++の仕組みです。

しかし、それはあなたが心配すべきことではありません。正直なところ、単純なコンストラクター/デストラクターの呼び出しが気になる場合は、手動で最適化する必要がある (したがって、独自のコードを作成する) コードを使用しているか、コードを時期尚早に最適化しているかのいずれかです。重要なのは、コンストラクタ/デストラクタが呼び出されるかどうかではありません。重要なのは、結果のコードがどれだけ速いかです。

unique_ptr は、指定されたメモリの排他的所有権を持ちます。偶発的なメモリ リークは発生しません。

はい、そうなります。

個人的には、次のいずれかを行っていると思います。

  • オブジェクトのコピーについて過度に偏執的である。shared_ptrこれは、コンテナに をコピーするのはコストがかかりすぎると考えているという事実による証拠です。これは、C++ プログラマの間で非常に一般的な病気です。コピーすることが常に良いことだと言っているわけではありませんがshared_ptr、コンテナー内の a をコピーすることに執着することは、例外的な状況以外ではばかげています。

  • 移動セマンティクスの適切な使用方法を認識していません。オブジェクトのコピーに費用がかかり、移動に費用がかからない場合は、それらをコンテナーに移動します。オブジェクトに既にポインターの間接化が含まれている場合、ポインターの間接化を行う理由はありません。オブジェクトへの sではなく、オブジェクト自体で移動を使用してunique_ptrください。

  • 代替手段を無視します。つまり、Boost のポインター コンテナーです。彼らはあなたが望むすべてを持っているようです。それらはオブジェクトへのポインターを所有していますが、外部的には、ポインターのセマンティクスではなく値のセマンティクスを持っています。それらは例外セーフであり、コピーはポインターで行われます。unique_ptrコンストラクタ/デストラクタの「オーバーヘッド」はありません。

于 2012-08-09T11:22:11.830 に答える
1

記事で挙げた3つの条件は、Boost Pointer Container Libraryを使えば取得できるようです。

于 2009-06-05T20:06:59.520 に答える