weak_ptr
とshared_ptr
の使い方を理解しています。オブジェクト内の参照の数を数えることで、shared_ptr
の仕組みを理解しています。 weak_ptr
はどのように機能しますか?ブーストのソースコードを読み通してみましたが、ブーストの使い方を理解するのに十分なブーストの知識がありません。
ありがとう。
_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つのアトミックインクリメント/デクリメントを保存します)。