45

私の現在のプロジェクトでは、boost::shared_ptrかなり広範囲に使用しています。

最近、私の仲間のチームメイトもを使い始めましweak_ptrた。どちらをいつ使うかわかりません。

weak_ptrこれとは別に、に変換したい場合はどうすればよいですかshared_ptr。ロックをオンにweak_ptrして作成するとshared_ptr、他のスレッドのコードに影響しますか?

4

4 に答える 4

70

一般的および要約、

強力なポインタは、それ自体の有効性を保証します。たとえば、次の場合に使用します。

  • あなたは指し示されているオブジェクトを所有しています。あなたはそれを作成し、それを破壊します
  • オブジェクトが存在しない場合、動作は定義されていません
  • オブジェクトが存在することを強制する必要があります。

弱いポインタは、自身の有効性を知ることを保証します。たとえば、次の場合に使用します。

  • あなたはそれにアクセスしますが、それはあなたのものではありません。
  • オブジェクトが存在しない場合の動作を定義しました

弱いポインタのLock()は、強いポインタを返します。これは、弱いポインタにアクセスする方法です。オブジェクトが無効になった場合(削除された場合など)、強力なポインターはNULLになります。それ以外の場合は、オブジェクトを指します。これを確認する必要があります。

このように設定されているため、オブジェクトを使用中に誤って削除することはありません。これは、一時的な(ローカルの)強力なポインターを作成したため、その強力なポインターが残っている間、オブジェクトの存在を保証するためです。オブジェクトの使用を終えたら、通常、強力なポインターをスコープから外します(または再割り当てします)。これにより、オブジェクトを削除できます。マルチスレッドの場合は、スレッドセーフが組み込まれていない他のものと同じように注意して扱ってください。マルチスレッドの場合は、上記の保証が適用されることに注意してください。AFAIK彼らはそれを超えて特別なことは何もしません。

ブースト共有ポインターには、ガベージコレクターのような機能もあります。これは、オブジェクトへの最後の強力なポインターがなくなるか、別の場所を指すと、オブジェクトが削除されるためです。

他の回答で言及されているパフォーマンスと循環依存関係もあります。

基本的に、ブースト共有ポインターライブラリを使用すると、プログラムの作成を台無しにすることはできませんが、ポインター、オブジェクトの所有権、および存続期間を適切に設計するために時間をかけることに代わるものではありません。そのような設計がある場合は、ライブラリを使用してそれを適用できます。そのような設計がない場合、以前とは異なる問題が発生する可能性があります。

于 2010-01-10T06:07:53.630 に答える
23

weak_ptr作成するオブジェクトに周期的な参照が含まれている場合、つまり自分自身に背を向けshared_ptrているオブジェクトへの参照がある場合に使用shared_ptrします。これは、shared_ptr循環参照を処理できないためです。両方のオブジェクトがスコープ外になると、相互参照はそれらが「ガベージコレクション」されないことを意味するため、メモリが失われ、メモリリークが発生します。は参照カウントを増加させないためweak_ptr、循環参照の問題は発生しません。これはまた、一般的に、参照カウントされているものへのポインターを取得したいだけで、その参照カウントを増やしたくない場合は、を使用することを意味しますweak_ptr

それ以外の場合は、を使用できますshared_ptr

詳細については、Boostのドキュメントを確認してください。

于 2010-01-10T05:37:54.377 に答える
6

共有ポインターは参照カウントを実装します。弱ポインタ​​ーは参照カウントに影響しません。オブジェクトへの共有ポインターがない場合は、弱ポインタ​​ーのみがオブジェクトを削除し、弱ポインタ​​ーはオブジェクトが失われたことを通知します。

弱いポインタを使用する理由は2つあります。

  1. 参照カウントの増加/減少のコストを排除するため。ただし、エラーが発生しやすく、実際には多くの時間を節約できないため、これを行うべきではありません。
  2. 簿記のデータ構造では、たとえば、「生きている」、つまり他の場所で使用されているすべてのオブジェクトFooのインデックスがあり、すべての「実際の」使用が終了した場合にFooをインデックスに残したくない場合があります。これは、弱ポインタ​​ーの基本的な現実的なユースケースです。もちろん他にも存在します。

したがって、一般的に、参照されるオブジェクトを削除させたいことがわかっていて、それを検出したい場合にのみ、弱ポインタ​​ーを使用することをお勧めします。その他の場合は、共有ポインター(参照カウント)または直接ポインター、特にを使用します。オブジェクトが削除されないことがわかっている場合は、メソッドのローカル変数で。エラーが発生しやすくなりますが、共有ポインタよりも高速です。

NB循環オブジェクトは弱ポインタ​​ーを必要としません。代わりに、最も適切に構築されたプログラムで、調理されていない通常のポインターを使用できます。ただし、弱いポインタはリスクが低くなります。

于 2010-01-10T05:38:10.413 に答える
-10

ガベージコレクターを実装しようとしているのでない限り、弱いポインターを使用しようとしないでください。これは、問題が発生する可能性のあるすべてのものを追跡するのが難しいため、C++ではホットなアイデアではありません。

于 2010-01-10T12:09:48.563 に答える