弱い参照
弱い参照(英: weak reference、ウィークリファレンス)あるいは弱参照とは、参照先のオブジェクトをガベージコレクタから守ることのできない参照のことである。弱い参照からのみによって参照されるオブジェクトは到達不可能とみなされ、従っていつでも解放することができる。弱い参照は、通常の参照(強い参照、強参照)による諸問題を解決するために用いられる。PythonやJavaをはじめとするガベージコレクタを実装したオブジェクト指向プログラミング言語の多くは、弱い参照を実装している。
概要
[編集]ガベージコレクタ (GC) はメモリオブジェクトのライフサイクル管理を自動化し、メモリリークを防ぐために用いられる。GCの方式のひとつとして参照カウント方式があり、これはオブジェクトごとに参照の数を記録する領域(参照カウンタ)を用意し、その数が0になった時点でオブジェクトを解放するというものである。この方式のGCは、あるオブジェクト間で参照が循環した場合にそれらを解放することができない(循環参照)。そのため、相互に参照しあったオブジェクト群はメモリリークの原因となる。この問題は、強い参照を弱い参照で置き換えることで解決することが可能な場合がある。一方、マーク・アンド・スイープ方式やコピーGC方式では循環参照によるメモリリークは発生しないが、非意図的オブジェクト保持(unintentional object retention)が引き起こすメモリリークを強参照のみによる実装で解消することは難しく煩雑であり、実装を簡略化するために弱参照が用いられることがある。
弱参照で参照されているオブジェクトは、アプリケーションコード側ではいつガベージコレクションされるか分からず、弱参照経由では直接オブジェクト参照として扱うことはできない。オブジェクト参照として利用するためには、弱参照から一時的な強参照にいったん変換し、GCから保護する必要がある。一時的な強参照の格納先には通例ライフサイクルが短くスコープの狭いローカル変数を利用し、オブジェクト参照が不要になった時点ですみやかに解放する。
弱い参照が便利なひとつの例として、アプリケーション内で参照されている変数を追跡するケースがある[1]。この追跡リストは、対象オブジェクトに対して弱い参照で参照しなければならない(弱いコレクション)。そうしなければ、一度リストに加えられたオブジェクトはリストによって参照されるため、プログラムが停止するまで半永久的に解放されることはない。
バリエーション
[編集]弱い参照のうち、さらに複数の強度を持つ言語もある。例えば、Javaにはjava.lang.ref
パッケージにて、弱い参照WeakReference
、ファントム参照PhantomReference
、ソフト参照SoftReference
が定義されている。また、WeakReference
によるハッシュテーブルとしてjava.util.WeakHashMap
が定義されている。
C++のように、元々ガベージコレクタのない言語で、その代替機能をライブラリでサポートし、その中で弱い参照・強い参照の機能を提供しているものもある。例えば参照カウント方式のスマートポインタを実現するC++のクラステンプレートとして、Boost C++ライブラリのboost::shared_ptr
やC++11以降のstd::shared_ptr
が存在するが、これらは「強い参照」に該当する。対応する「弱い参照」は、それぞれboost::weak_ptr
とstd::weak_ptr
である。通常の(言語組み込みの)ポインタは参照の数に影響しないと言う意味で「弱い参照」と考えることもできるが、弱い参照はオブジェクトが到達不可能になったことを知っているべきなので、ポインタは本当の意味での弱い参照ではない。