参照カウント

参照カウントとは



参照カウント(英:reference counting)は、メモリオブジェクトのライフサイクルを管理する方式の一つです。ガベージコレクションの実装や、コピーオンライトの実現にも用いられます。

仕組み



全てのオブジェクトに「参照カウント」と呼ばれる整数値を付与します。これは、そのオブジェクトへの参照(ポインタ)がいくつ存在するかを示す数値です。
オブジェクトへの参照が増減するたびに、この値を更新します。参照カウントが0になったオブジェクトは、システムから破棄されることが許されます。ただし、ファイルキャッシュのように、参照カウントが0になっても直ちに破棄せず、再利用のために保持する場合もあります。この場合、オブジェクトの破棄判断には別の基準が必要です。

独立したデータを擬似的に表現する場合は、以下の処理を行います。

オブジェクトのコピー要求時には、実際にはコピーを行わず、元のオブジェクトへの参照を返し、参照カウントを1増やします。
オブジェクトの変更時には、
参照カウントが1であれば、そのまま書き換えます。
参照カウントが2以上であれば、元のオブジェクトをコピーして、参照カウントが1の新オブジェクトを作成し、それを書き換えます。元のオブジェクトの参照カウントは1減らします。

長所



単純かつ高速: 処理が単純で、高速に動作します。
即時解放: オブジェクトの参照がなくなった時点で即座に破棄されるため、メモリが少ない環境で特に有効です。
専用スレッド不要: ガベージコレクタのような専用のスレッドやプロセスを必要としません。
複合的な実装: ガベージコレクションコピーオンライトを同時に実装できます。
決定論的な動作: オブジェクトの解放タイミングを確実に制御できます。

短所



循環参照: オブジェクト同士が互いに参照し合う場合、参照カウントが0にならず、破棄されない場合があります(メモリリーク)。
大量解放時の遅延: 大量のオブジェクトが一斉に解放される場合、処理が遅くなることがあります。
コンテナオブジェクト: 解放されるオブジェクトが多くのオブジェクトを参照している場合に遅延が発生しやすいです。
オーバーヘッド: 対象オブジェクトが小さく、コピーが頻繁に行われる場合、参照カウントの管理にオーバーヘッドが生じます。
マルチスレッド: マルチスレッド環境では、参照カウントの増減をスレッドセーフにする必要があり、ロック機構によるオーバーヘッドが発生します。

用途



文字列オブジェクトの実装によく用いられます。文字列は内部で他のオブジェクトを参照しないため、参照カウントの短所の影響を受けにくいからです。単純なビット列などのデータも同様に適しています。

循環参照の問題点



参照カウントの大きな問題点は、循環参照によりオブジェクトが解放されなくなることです。例えば、C++のスマートポインタである `std::shared_ptr` を用いて自己参照や相互参照を持つクラスを定義すると、参照カウントが減らずにメモリリークが発生します。

この問題を避けるには、利用を終えた時点で明示的に参照を解除する必要がありますが、コードが複雑になり、スマートポインタの利点を損なってしまいます。そのため、多くの言語やライブラリでは、参照カウントを増加させない弱い参照(weak reference)を導入しています。C++では `std::weak_ptr` が相当します。

一方、マーク・アンド・スイープやコピーGC方式のガベージコレクションでは、循環参照によるメモリリークは発生しません。

Java.NET Frameworkでは参照カウントではなく、別のガベージコレクション方式を採用しており、循環参照によるメモリリークは発生しません。ただし、意図しないオブジェクトの保持を防ぐために、弱参照が使用されることもあります。

ウィキペディアでの例



ウィキペディアの「孤立した記事」は、参照カウントが0の記事を表示しているだけであり、孤立した記事からのみ参照されている記事は孤立した記事とは見なされません。

実用例



マイクロソフトのCOMオブジェクト
Objective-C、Swiftのオブジェクト
PerlPythonのガベージコレクタ(Pythonは世代別GCを併用)
C++の`std::shared_ptr`
Boost [[C++ライブラリ]]の`boost::shared_ptr`、`boost::intrusive_ptr`
POCO C++ Libraries の `SharedPtr`
GLibのオブジェクトシステムGObject
ファイルシステムハードリンク

参照カウントは、シンプルで高速なメモリ管理手法ですが、循環参照に注意する必要があります。用途に合わせて、他のガベージコレクション方式や弱い参照と組み合わせて利用することで、より効率的なメモリ管理を実現できます。

もう一度検索

【記事の利用について】

タイトルと記事文章は、記事のあるページにリンクを張っていただければ、無料で利用できます。
※画像は、利用できませんのでご注意ください。

【リンクついて】

リンクフリーです。