オブジェクト指向プログラミング(OOP)では、オブジェクトの有効期間は、オブジェクトの 作成から破棄までの期間です。プログラミング コンテキストによっては、オブジェクトの有効期間は、オブジェクトを表す変数の有効期間と一致します。オブジェクトが参照によってアクセスされる他のコンテキストでは、オブジェクトの有効期間は変数の有効期間によって決定されません。たとえば、変数を破棄すると、参照のみが破棄され、参照先のオブジェクトは破棄されない場合があります。
用語
オブジェクトの有効期間の側面は、プログラミング言語間および言語の実装によって異なります。中核となる概念は比較的共通ですが、用語は異なります。たとえば、作成と破棄の概念は、constructとdestruct と呼ばれることもあり、言語要素はコンストラクター(ctor) とデストラクタ(dtor) と呼ばれます。
決定論
オブジェクトの作成は一般的に決定論的ですが、破棄はプログラミング コンテキストによって異なります。決定論的な破棄が可能なコンテキストもあれば、不可能なコンテキストもあります。特に、ガベージ コレクション環境では、ガベージ コレクターが選択したときにオブジェクトが破棄されます。
作成と破棄の構文は、プログラミング コンテキストによって異なります。C++、C#、Java などの多くのコンテキストでは、 のような特殊な構文を使用してオブジェクトが作成されます。手動のメモリ管理を提供する C++ では、キーワードを使用してオブジェクトが破棄されます。明示的な破棄構文のない C# と Java では、ガベージ コレクターが未使用のオブジェクトを自動的に非決定的に破棄します。
new typename()delete
自動破棄の代替となる決定論的なアプローチは、コードがオブジェクトの参照カウントをゼロに減らしたときにオブジェクトが破棄されるというものです。
オブジェクト プールでは、オブジェクトを事前に作成して再利用できるため、オブジェクトの見かけ上の作成と破棄が実際の作成と破棄と一致しない場合があります。プールでは、作成の場合は再初期化、破棄の場合は終了処理が行われます。作成と破棄はどちらも非決定的である可能性があります。
静的メモリ割り当てを持つオブジェクトの有効期間はプログラムの実行と一致しますが、さまざまな静的オブジェクトの作成と破棄の順序は通常は非決定的です。
ライフサイクル
オブジェクトのライフサイクルとは、作成から破棄までの間など、オブジェクトが経験するイベントを指します。
ライフサイクルには通常、メモリ管理と、割り当て後および割り当て解除前の操作が含まれます。オブジェクトの作成は通常、メモリの割り当てと初期化で構成されます。初期化には、フィールドへの値の割り当てと初期化コードの実行が含まれます。オブジェクトの破棄は通常、ファイナライズ(クリーンアップとも呼ばれます) とメモリの割り当て解除(解放とも呼ばれます) で構成されます。これらの手順は通常、割り当て、初期化、ファイナライズ、割り当て解除の順序で進行します。
プログラミングのコンテキストに基づいて、これらの手順は部分的または完全に自動化され、一部の手順はカスタマイズできます。
カスタマイズの頻度は、手順とプログラミング コンテキストによって異なる傾向があります。初期化は、最も一般的にカスタマイズされる手順です。ファイナライズは、決定論的な破棄を行う言語 (特に C++) では一般的ですが、ガベージ コレクションを行う言語ではほとんどありません。割り当てはほとんどカスタマイズされず、割り当て解除は通常カスタマイズできません。
創造
オブジェクトを作成する方法は、プログラミング コンテキストによって異なります。一部のクラス ベースの言語では、コンストラクターが初期化を処理します。他のメソッドと同様に、コンストラクターは、異なる初期状態での作成をサポートするために オーバーロードできます。
破壊
通常、オブジェクトは不要になるとメモリから削除されます。ただし、十分なメモリがある場合やプログラムの実行時間が短い場合は、オブジェクトの破棄が行われず、プロセスの終了時にメモリが単に解放されることがあります。
場合によっては、オブジェクトの破棄は、特にガベージ コレクションを使用する場合や、オブジェクトが単純な古いデータ構造である場合に、メモリの割り当て解除のみで構成されます。その他の場合では、割り当て解除の前にクリーンアップが実行され、特にメンバー オブジェクトが破棄される (手動メモリ管理の場合) か、オブジェクトから他のオブジェクトへの参照が削除されて参照カウントが減算されます (参照カウントの場合)。これは自動的に実行される場合もあれば、オブジェクトに対して特別な破棄メソッドが呼び出される場合もあります。
オブジェクトの有効期間が決定論的なクラスベースの言語、特に C++ では、インスタンスが削除されるときにメモリが解放される前にデストラクタが呼び出されます。C++ では、デストラクタはコンストラクタとさまざまな点で異なります。デストラクタはオーバーロードできず、引数を持つ必要はなく、クラスの不変条件を維持する必要がなく、例外をスローするとプログラムが終了することがあります。
ガベージ コレクションでは、プログラムからアクセスできなくなったオブジェクトは破棄されることがあります。ガベージ コレクターは、 メモリの割り当てを解除する前にファイナライザーを呼び出します。
オブジェクトを破棄すると、そのオブジェクトへの参照はすべて無効になります。手動メモリ管理では、既存の参照はすべて未解決の参照になります。ガベージ コレクションでは、オブジェクトは参照がなくなった場合にのみ破棄されます。
一貫性
オブジェクトの有効期間は、割り当てが完了したときに始まり、割り当て解除が開始されたときに終了します。したがって、初期化中および終了中、オブジェクトは有効ですが、一貫性のある状態ではない可能性があります。初期化が完了してから終了が開始されるまでの期間は、オブジェクトが有効であり、一貫性のある状態にある期間です。
作成または破棄が失敗した場合、オブジェクトまたは関連オブジェクトが不整合な状態になる可能性があるため、エラー報告 (例外の発生など) が複雑になる可能性があります。
静的変数の場合、その有効期間がプログラムの実行と一致するため、プログラムの実行は通常の実行の前または後に行われるため、作成または破棄のエラーは問題になります。
クラスベースのプログラミング
クラスベースのプログラミングでは、オブジェクトの作成はインスタンス化(クラスのインスタンスの作成)とも呼ばれます。作成と破棄は、コンストラクターとデストラクターを介してカスタマイズでき、場合によっては個別の初期化メソッドと終了メソッドを使用してカスタマイズできます。
特に、コンストラクターは、オブジェクトが作成されるまで利用可能なオブジェクト (インスタンス) がないためクラス メソッドですが、デストラクター、初期化子、およびファイナライザーはインスタンス メソッドです。
さらに、コンストラクタと初期化子は引数を受け入れることが多いのに対し、デストラクタとファイナライザは暗黙的に呼び出せることが多いため、通常は引数を受け入れません。
リソース管理
ライフタイムが決定論的なオブジェクトを持つ言語では、ライフタイムはリソース管理を便乗するために使われることがあります。これは、リソース取得は初期化である(RAII) イディオムと呼ばれます。リソースは初期化中に取得され、終了時に解放されます。ライフタイムが決定論的でない (つまり、ガベージ コレクションされる) 言語では、メモリの管理は一般に他のリソースの管理とは別に行われます。
例
C++
C++ クラスは次のようにデフォルトで宣言できます。
クラスFoo {};
自動コンテキストで宣言された場合、オブジェクトは宣言されたブロックの終了時に破棄されます。
int bar () { Foo foo (); // foo はここで破棄されます}
動的に作成された場合は、明示的に破棄されるまで存続します。
int bar () { Foo * pFoo = new Foo (); pFoo を削除します; }
ジャワ
Java クラスは次のようにデフォルトで宣言できます。
クラス Foo {}
インスタンスが作成されると (つまりnew Foo())、参照がなくなり、ガベージ コレクターによって削除されるまで存続します。
