共有ポインタについて読んで、使い方を理解しました。しかし、共有ポインターの循環依存の問題と、弱いポインターがそれらの問題をどのように修正するかを理解していませんでした。誰でもこの問題を明確に説明できますか?
2 に答える
問題はそれほど複雑ではありません。-->共有ポインタを表現してみましょう:
The rest of the program --> object A --> object B
^ |
\ |
\ v
object C
したがって、共有ポインターを使用した循環依存関係があります。各オブジェクトの参照カウントは?
A: 2
B: 1
C: 1
ここで、プログラムの残りの部分 (またはいずれにせよ、A への共有ポインターを保持する部分) が破棄されたとします。次に、A の参照カウントが 1 減るので、サイクル内の各オブジェクトの参照カウントは 1 になります。では、何が削除されるのでしょうか? 何もない。しかし、何を削除したいのでしょうか? プログラムの残りの部分からオブジェクトにアクセスできないため、すべてです。
したがって、この場合の修正は、C から A へのリンクを弱いポインターに変更することです。弱いポインターはターゲットの参照カウントに影響を与えません。つまり、プログラムの残りの部分が A を解放すると、その参照カウントは 0 になります。したがって、それは削除され、したがって B も削除され、したがって C も削除されます。
ただし、プログラムの残りの部分が A を解放する前に、C はウィーク ポインターをロックすることで、いつでも A にアクセスできます。これは、C がアクティブに A を処理している限り、それを共有ポインターに昇格させます (そして、A の参照カウントを 2 に増やします)。つまり、これが行われている間に A が別の方法で解放された場合、その参照カウントは 1 に落ちるだけです。 A を使用する C のコードはクラッシュせず、短期間の共有ポインターが破棄されるたびに A が削除されます。これは、ウィーク ポインターをロックしたコード ブロックの最後にあります。
一般に、ウィーク ポインターを配置する場所を決定するのは複雑な場合があります。サイクルを破る場所を選択するには、サイクル内のオブジェクト間にある種の非対称性が必要です。この場合、A がプログラムの残りの部分によって参照されるオブジェクトであることがわかっているため、サイクルを中断する場所は A を指している場所であることがわかります。