参照カウント

参照カウント（さんしょうカウント、）は、メモリオブジェクトのライフサイクル（寿命）管理に使用される方式のひとつ。ガベージコレクションの実装方法およびガベージコレクタの動作方法のひとつとしても利用される。また、コピーオンライトの実装方法としても多用される。
処理の概要.
共有された単一のオブジェクトへの参照ではなく、独立したデータを擬似的に表現する場合は、下記の処理を追加する。
特徴.
長所.
また、システムの空き時間（アイドル時）に動作する方式のガベージコレクションとは異なり、参照カウント方式は通例決定論的 (deterministic) に動作するため、オブジェクトの解放タイミングを確実に制御したい場合に有利である。
用途.
文字列オブジェクトの実装手段としては適しており、多くのシステムで採用されている。
これは、文字列であれば内部で他のオブジェクトを参照しないので、短所の多くには影響がないためである。
単純なビット列などのデータも同様に適している。
循環参照の問題点.
参照カウントには、循環参照によりデータを解放できなくなる（メモリリークが発生する）という問題がある。
例えばC++向けのBoost C++ライブラリあるいはC++11規格以降の標準C++ライブラリには、参照カウントベースのスマートポインタを実現するクラステンプレートとして、それぞれcodice_1あるいはcodice_2が用意されているが、これを使って自己参照あるいは相互参照を持つクラスを定義してしまうと、参照カウントが適切に減らされずに互いのインスタンスが解放されなくなってしまう。
class A {
public:
 std::shared_ptr<class B> m_refB;
 ~A() {
 std::cout « "Destructor of A is called." « std::endl;
};
class B {
public:
 std::shared_ptr<class A> m_refA;
 ~B() {
 std::cout « "Destructor of B is called." « std::endl;
};
void doTest() {
 std::shared_ptr<A> refA(new A());
 std::shared_ptr<B> refB(new B());
 refA->m_refB = refB;
 refB->m_refA = refA;
} // ここで A および B のデストラクタが呼ばれなくなり、メモリリークする。
int main() {
 doTest();
 return 0;
循環参照によるメモリリークを回避するためには、利用を終えたタイミングで明示的に参照を解除するコードを記述するなどの方法があるが、ソースコードが煩雑になってしまい、スマートポインタの利点を打ち消してしまう。
この問題を解消するために、多くのプログラミング言語やソフトウェアライブラリあるいはシステムで弱い参照 (ウィークリファレンス、) が導入されている。弱い参照とは、参照カウントを増加させない参照である。例えばC++ではcodice_3あるいはcodice_4などが該当する。
一方、マーク・アンド・スイープやコピーGCによるガベージコレクションでは、循環参照によるメモリリークの問題は発生しない。
なお、Javaや.NET Frameworkでは、いずれも参照カウントベースではないガベージコレクション方式を採用しており、循環参照によるメモリリークは発生しない。例えば以下のJavaコードは合法であり、循環参照していたとしてもガベージコレクションの回収対象となる。
class A {
 public B b;
class B {
 public A a;
public class Test {
 public static void doTest() {
 A a = new A();
 B b = new B();
 a.b = b;
 b.a = a;
 } // 十分な時間が経過すれば、いずれ GC により回収される。
 public static void main(String[] args) {
 doTest();
ただし、非意図的オブジェクト保持（unintentional object retention）が引き起こすメモリリークを回避するために、通常の参照（強参照）の代わりにのような弱参照クラスのインスタンスを使うこともある。
ウィキペディアでの例.
ウィキペディアの「」は、参照カウントが0のものを表示しているだけなので、孤立した記事だけから参照されている記事は孤立した記事と見なされていない。