web-dev-qa-db-ja.com

weak_ptrはどのように機能しますか?

weak_ptrshared_ptrの使い方を理解しています。オブジェクト内の参照の数を数えることで、shared_ptrの仕組みを理解しています。 weak_ptrはどのように機能しますか?ブーストのソースコードを読み通してみましたが、ブーストの使い方を理解するのに十分なブーストの知識がありません。

ありがとう。

57
Oliver Zheng

_shared_ptr_は、追加の「カウンター」オブジェクト(別名「共有カウント」または「制御ブロック」)を使用して、参照カウントを格納します。 (ところで:その「カウンター」オブジェクトは、削除者も格納します。)

すべての_shared_ptr_および_weak_ptr_には、実際の指示先へのポインターと、「カウンター」オブジェクトへの2番目のポインターが含まれています。

_weak_ptr_を実装するには、「counter」オブジェクトに2つの異なるカウンターを格納します。

  • 「使用カウント」は、オブジェクトを指す_shared_ptr_インスタンスの数です。
  • 「弱いカウント」は、オブジェクトを指す_weak_ptr_インスタンスの数であり、「使用カウント」がまだ0より大きい場合は1を加算したものです。

「使用回数」がゼロになると、指示先は削除されます。

「counter」ヘルパーオブジェクトは、「weak count」がゼロに達すると削除されます(つまり、「use count」もゼロでなければなりません(上記を参照)。

_shared_ptr_から_weak_ptr_を取得しようとすると、ライブラリは「使用カウント」をアトミックにチェックし、0より大きい場合はインクリメントします。それが成功した場合、_shared_ptr_を取得します。 「使用カウント」がすでにゼロの場合は、代わりに空の_shared_ptr_インスタンスを取得します。


[〜#〜] edit [〜#〜]:では、両方のカウントがゼロになったときに「counter」オブジェクトを解放するのではなく、なぜ弱いカウントに1を追加するのですか?良い質問。

あるいは、「使用カウント」と「弱いカウント」の両方がゼロになったときに「カウンター」オブジェクトを削除することもできます。最初の理由は次のとおりです。2つの(ポインターサイズの)カウンターをアトミックにチェックすることは、すべてのプラットフォームで実行できるわけではなく、1つのカウンターだけをチェックするよりも複雑です。

別の理由は、削除が実行を終了するまで削除機能が有効である必要があることです。削除機能は「カウンター」オブジェクトに格納されているため、「カウンター」オブジェクトは有効なままである必要があります。オブジェクトに_shared_ptr_が1つと_weak_ptr_が1つあり、それらが並行スレッドで同時にリセットされた場合にどうなるかを検討してください。 _shared_ptr_が最初に来るとしましょう。 「使用カウント」をゼロに減らし、削除機能の実行を開始します。ここで、_weak_ptr_は「弱いカウント」をゼロに減らし、「使用カウント」もゼロであることを確認します。したがって、「counter」オブジェクトを削除し、それとともに削除者も削除します。削除機能がまだ実行されている間。

もちろん、「counter」オブジェクトが生き続けることを保証するためのさまざまな方法がありますが、「weak count」を1つ増やすことは、非常にエレガントで直感的な解決策だと思います。 「弱いカウント」は、「カウンター」オブジェクトの参照カウントになります。また、_shared_ptr_ sもカウンターオブジェクトを参照するため、「弱いカウント」をインクリメントする必要があります。

すべての_shared_ptr_は「カウンタ」オブジェクトへの参照であるため、おそらくさらに直感的な解決策は、すべての_shared_ptr_の「ウィークカウント」をインクリメントすることです。

すべての_shared_ptr_インスタンスに1つを追加することは、最適化です(_shared_ptr_インスタンスをコピー/割り当てするときに1つのアトミックインクリメント/デクリメントを保存します)。

96
Paul Groke