コンピュータプログラミングにおいて、弱参照とは、強い参照とは異なり、参照先のオブジェクトをガベージコレクタによるガベージコレクションから保護しない参照のことである。弱参照のみで参照されるオブジェクト(つまり、「オブジェクトに到達するすべての参照チェーンには、リンクとして少なくとも 1 つの弱参照が含まれている」オブジェクト)は、弱到達可能とみなされ、到達不能として扱うことができるため、いつでもガベージコレクションの対象になる可能性がある。ガベージコレクション言語の中には、C#、Lua、Java、Lisp、OCaml、 MATLAB [1]、Perl、Python [2]、PHPバージョン 7.4 以降など、さまざまなレベルの弱参照を特徴としたりサポートしたりするものがある。[ 3]
用途
弱参照には、いくつかの一般的な用途があります。参照カウントガベージ コレクションを使用する場合、弱参照は、サイクル内のリンクに弱参照を使用することで、参照サイクルを中断できます。オブジェクトに関する補助データを保持するなど、キーがオブジェクト (への参照) である連想配列(マッピング、ハッシュ マップ) がある場合、キーに弱参照を使用すると、キーとして使用されているためオブジェクトが存続し続けることを回避できます。オブザーバー パターン(特にイベント処理) など、他のオブジェクトが登録されているオブジェクトがある場合、強参照が保持されている場合は、オブジェクトを明示的に登録解除する必要があります。そうしないと、メモリ リークが発生します (リスナーの失効問題)。一方、弱参照では登録解除の必要がなくなります。必要に応じて再作成できるキャッシュ データを保持する場合、弱参照を使用するとキャッシュを再利用でき、実質的に破棄可能なメモリが生成されます。この最後のケース (キャッシュ) は他のケースとは異なり、必要な場合にのみオブジェクトがガベージ コレクションされることが望ましいため、弱参照内でより細かい区別が必要であり、ここではより強い形式の弱参照です。多くの場合、弱参照を直接使用する必要はなく、代わりにキーまたは値が弱参照である弱配列またはその他のコンテナーを使用するだけです。
ガベージコレクション
ガベージ コレクションは、未使用のオブジェクトをクリーンアップして、メモリ リークやデータ破損の可能性を減らすために使用されます。ガベージ コレクションには、トレースと参照カウントの 2 つの主な種類があります。参照カウント スキームは、特定のオブジェクトへの参照の数を記録し、参照カウントが 0 になったときにオブジェクトを収集します。参照カウントでは、一度に 1 つのオブジェクトしか収集できないため、循環参照を収集できません。他のオブジェクトによって直接参照されておらず、到達不能な相互参照オブジェクトのグループは、そのため永久に常駐する可能性があります。アプリケーションがこのような到達不能なオブジェクトのグループを継続的に生成すると、メモリ リークが発生します。弱参照 (参照カウントでカウントされない参照) を使用すると、グループ内の参照の一部に弱参照を使用して参照サイクルを回避できる場合、循環参照の問題を解決できます。
このような強い参照と弱い参照の区別がよく見られるのは、ドキュメント オブジェクト モデル(DOM) などのツリー構造です。この場合、親から子への参照は強いですが、子から親への参照は弱いです。たとえば、Apple のCocoaフレームワークでは、このアプローチが推奨されています。[4]実際、オブジェクト グラフがツリーでない場合でも、オブジェクトの所有権の概念によってツリー構造が強制されることが多く、所有権関係は強くツリーを形成し、非所有権関係は弱くツリーを形成するのに必要ありません。このアプローチは、生のポインタを弱参照として使用するC++ (C++11 より前) では一般的です。ただし、このアプローチには、親ブランチが削除されたことを検出できないという欠点があります。C ++11標準以降、 Boostライブラリから継承されたshared_ptr と weakness_ptr を使用するソリューションが追加されました。
弱参照は、プログラムが弱参照のみでオブジェクトの重要性が低いことを示すことができるようにすることで、メモリ内の不要なオブジェクトの数を最小限に抑えるためにも使用されます。[要出典]
バリエーション
言語によっては、弱参照の強さに複数のレベルがある。例えば、Java では、強さの降順で、ソフト参照、弱参照、ファントム参照があり、 java.lang.refパッケージ で定義されている。[5]各参照タイプには、到達可能性の概念が関連付けられている。ガベージ コレクター (GC) は、オブジェクトの到達可能性のタイプを使用して、オブジェクトをいつ解放するかを決定する。GC がソフト到達可能なオブジェクトを解放しても安全だが、JVM がメモリを節約できると判断した場合 (JVM に未使用のヒープ領域が大量にある場合など)、GC は解放しないことを決定することもある。GC は、弱到達可能なオブジェクトに気付くとすぐにそのオブジェクトを解放する。他の参照タイプとは異なり、ファントム参照を追跡することはできない。一方、ファントム参照は、オブジェクトが解放されたときにプログラムに通知するメカニズムを提供する (通知は ReferenceQueues を使用して実装される)。
C# では、弱参照はオブジェクトの復活を追跡するかどうかで区別されます。この区別は強参照では発生しません。オブジェクトは、それに対する強参照がある場合には確定されないからです。デフォルトでは、C# の弱参照は復活を追跡しません。つまり、オブジェクトが復活しても弱参照は更新されません。これらは短い弱参照と呼ばれ、復活を追跡する弱参照は長い弱参照と呼ばれます。[6]
C++などの一部の非ガベージ コレクション言語では、ガベージ コレクション ライブラリのサポートの一環として、弱参照/強参照機能が提供されています。Boost C++ ライブラリは、強参照と弱参照を提供しています。通常の C++ ポインターをスマート ポインターの弱参照として使用するのは誤りです。このような使用方法では、強参照カウントが 0 になり、オブジェクトが削除されたことを検出する機能が失われるからです。さらに悪いことに、別の強参照がすでに特定のプレーン ポインターを追跡しているかどうかを検出できません。これにより、2 つ (またはそれ以上) のスマート ポインターが同じプレーン ポインターを追跡する可能性が生じます (これらのスマート ポインターの参照カウントが 0 になり、オブジェクトが削除されるとすぐに破損が発生します)。
例
弱参照は、アプリケーションで参照されている現在の変数のリストを保持するときに役立ちます。このリストには、オブジェクトへの弱リンクが必要です。そうでない場合、オブジェクトがリストに追加されると、そのリストによって参照され、プログラムの期間中は存続します。
ジャワ
1998年のJava 1.2では2種類の弱参照が導入されました[7]。1つは「ソフト参照」と呼ばれ(GC管理のメモリ内キャッシュの維持に使用されることを意図していますが、Android [8]のような動的ヒープを備えた一部のプラットフォームでは実際にはあまりうまく機能しません)、もう1つは単に「弱参照」と呼ばれています。また、危険で非効率的なfinalize()メカニズムの代替として、「ファントム参照」と呼ばれる関連する実験的なメカニズムも追加されました[9]。
弱参照が作成され、その後コードの他の場所でget()実際のオブジェクトを取得するために使用された場合、その弱参照はガベージコレクションを防ぐのに十分な強さではないため、(オブジェクトへの強参照がない場合)get()突然nullを返し始める可能性があります。[10]
java.lang.ref.WeakReferenceをインポートします。
パブリッククラスReferenceTest { public static void main ( String [] args ) throws InterruptedException { WeakReference r = new WeakReference ( "I'm here " ); StrongReference sr = new StrongReference ( " I'm here" ); System.out.println ( " Before gc : r = " + r.get ( ) + " , static=" + sr.get ( ) ) ; System.gc ( ) ; Thread.sleep ( 100 ) ;
// r.get() のみが null になります。System.out.println
( " After gc : r=" + r.get ( ) + " , static=" + sr.get ( ) ) ; } }
弱参照のもう 1 つの用途は、キャッシュの書き込みです。たとえば、弱ハッシュ マップを使用すると、弱参照を介して参照されるさまざまなオブジェクトをキャッシュに格納できます。ガベージ コレクターが実行されると (たとえば、アプリケーションのメモリ使用量が十分に高くなると)、他のオブジェクトによって直接参照されなくなったキャッシュされたオブジェクトはキャッシュから削除されます。
雑談
| s1 s2 |
s1 := 'hello' copy . "これは強い参照です"
s2 := 'world' copy . "これは強い参照です"
a := WeakArray with: s1 with: s2 .
a printOn: Transcript .
ObjectMemory collectGarbage .
a printOn: Transcript . "両方の要素がまだ残っています"
s1 := nil . "強い参照が消えます"
ObjectMemory collectGarbage .
a printOn: Transcript . "最初の要素が消えました"
s2 := nil . "強い参照が消えます"
ObjectMemory collectGarbage .
a printOn: Transcript . "2 番目の要素が消えました"
ルア
弱いテーブル = setmetatable ({}, { __mode = "v" })
弱いテーブル. item = {}
print (弱いテーブル. item )
collectgarbage ()
print (弱いテーブル. item )
オブジェクティブC 2.0
Objective-C 2.0では、ガベージ コレクションだけでなく、自動参照カウントも弱参照の影響を受けます。次の例のすべての変数とプロパティは弱参照です。
@interface WeakRef : NSObject
{
__weak NSString * str1 ; __unsafe_unretained NSString * str2 ; }
@property (非アトミック、弱い) NSString * str3 ; @property (非アトミック、unsafe_unretained ) NSString * str4 ;
@終わり
weak( __weak) とunsafe_unretained( )の違いは__unsafe_unretained、変数が指しているオブジェクトが解放されるときに、変数の値が変更されるかどうかです。weakは に更新されnil、は変更されずに、ぶら下がりポインターunsafe_unretainedとして残ります。参照は、Mac OS X 10.7 "Lion"およびiOS 5以降、 Xcode 4.1 (iOS の場合は 4.2)とともに、ARC を使用する場合にのみObjective-C に追加されました。Mac OS X、iOS、および GNUstep の古いバージョンは、弱い参照としてのみ参照をサポートしています。
weakunsafe_unretained
class Node { public weakness Node prev ; // 弱参照は、二重リンクリストのノード間の循環参照を回避するために使用されますpublic Node next ; }
パイソン
>>> import weaknessref
>>> import gc
>>> class Egg :
... def spam ( self ):
... print ( "I'm alive!" )
...
>>> obj = Egg ()
>>> weakness_obj = weaknessref . ref ( obj )
>>> weakness_obj () . spam ()
I'm alive!
>>> obj = "Something else"
>>> gc . collect ()
35
>>> weakness_obj () . spam ()
トレースバック (最後の呼び出しが最後):
ファイル"<stdin>"、行1、<module>
AttributeError : 'NoneType' オブジェクトには属性 'spam' がありません
参照
参考文献
- ^ [1]
- ^ 8.8. weaknessref — 弱参照、Python 標準ライブラリ
- ^ 「PHP: WeakReference - マニュアル」.
- ^ 「実用的なメモリ管理」。developer.apple.com。
- ^ Nicholas, Ethan (2006 年 5 月 4 日)。「弱い参照を理解する」。java.net。2011年 3 月 3 日時点のオリジナルよりアーカイブ。2010年10 月 1 日閲覧。
- ^ ゴールドシュタイン、ズルバレフ、フラトウ 2012、131ページ。
- ^ “WeakReference (Java プラットフォーム SE 7)”. docs.oracle.com。
- ^ 「SoftReference - Android 開発者」。developer.android.com。
- ^ 「PhantomReference (Java Platform SE 7)」. docs.oracle.com .
- ^ https://web.archive.org/web/20110303225354/http://weblogs.java.net/blog/2006/05/04/understanding-weak-references Java の例
- Goldshtein, Sasha; Zurbalev, Dima; Flatow, Ido (2012)。Pro .NET Performance: C# アプリケーションの最適化。Apress。ISBN 978-1-4302-4458-5。
外部リンク
C++
- C++11 標準ライブラリ: std::weak_ptr リファレンス
- Boost 1.59 (C++ ライブラリ) : boost::weak_ptr リファレンス
ジャワ
- Java 開発者向け記事: 「参照オブジェクトとガベージ コレクション」
- Nicholas, Ethan (2006 年 5 月 4 日)。「弱い参照を理解する」。java.net。2010年8 月 19 日時点のオリジナルよりアーカイブ。2010年10 月 1 日閲覧。
{{cite web}}: CS1 maint: bot: 元の URL ステータス不明 (リンク) - RCache - 弱/ソフト参照ベースのキャッシュ用 Java ライブラリ
- Java の理論と実践: 弱参照によるメモリ リークの修正
PHP の
- 弱い参照
パイソン
- weaknessref — 弱参照 — Python 3 ドキュメント
- Fred L. Drake, Jr.、PEP 205: 弱参照、Python 機能拡張提案、2001 年 1 月。
