オブジェクトの有効期間

オブジェクト指向プログラミング(OOP)では、オブジェクトのオブジェクトの有効期間(またはライフ サイクル)は、オブジェクトの作成から破棄までの時間です。オブジェクトの存続期間のルールは言語間で大きく異なり、場合によっては特定の言語の実装間で異なり、特定のオブジェクトの存続期間はプログラムの 実行ごとに異なる場合があります。

場合によっては、オブジェクトの有効期間が、そのオブジェクトを値として持つ変数有効期間と一致することがあります (静的変数自動変数の両方)。しかし、一般に、オブジェクトの有効期間は、1 つの変数の有効期間に関連付けられません。多くの場合、多くのオブジェクト指向言語、特にガベージ コレクション(GC) を使用する言語ではデフォルトで、オブジェクトはヒープ上に割り当てられ、オブジェクトの有効期間は特定の変数の有効期間、つまり変数の値によって決まりません。オブジェクトの保持は、実際にはオブジェクト自体ではなくオブジェクトへの 参照に対応し、変数の破棄は参照を破棄するだけであり、基になるオブジェクトは破棄されません。

概要

オブジェクトの存続期間の基本的な考え方は単純ですが、オブジェクトが作成され、使用され、その後破棄されます。詳細は言語間および特定の言語の実装内で大幅に異なり、メモリ管理の実装方法と密接に関係しています。さらに、ステップ間、および言語レベルの概念と実装レベルの概念の間には、多くの細かい区別があります。用語は比較的標準的ですが、特定の用語にどのステップが対応するかは言語によって大きく異なります。

用語は通常、反意語のペアで表され、1 つは作成概念、もう 1 つは初期化/ファイナライズコンストラクター/デストラクターなど、対応する破棄概念に対応します。作成/破棄のペアは、他の用語の中でも、開始/終了とも呼ばれます。メモリ管理との類推で、割り当て割り当て解除または解放という用語も使用されますが、オブジェクトの作成と破棄には、単にメモリの割り当てと割り当て解除以上のものが含まれる場合があり、割り当てと割り当て解除は、それぞれ作成と破棄のステップとしてより適切に考慮されます。

決定論

主な違いは、オブジェクトの存続期間が決定的であるか非決定的であるかです。これは言語によって異なり、言語内でもオブジェクトのメモリ割り当てによって異なります。オブジェクトの有効期間は変数の有効期間とは異なる場合があります。

静的メモリ割り当てを持つオブジェクト、特に静的変数に格納されているオブジェクト、およびクラスモジュール(クラスまたはモジュール自体がオブジェクトで静的に割り当てられている場合) は、多くの言語で微妙な非決定性を持っています。その一方で、オブジェクトの有効期間は実行時間と一致しているように見えます。プログラムの作成と破棄の順序(どの静的オブジェクトが最初に作成され、どの静的オブジェクトが 2 番目に作成されるかなど) は、一般に非決定的です。[a]

自動メモリ割り当てまたは動的メモリ割り当てを備えたオブジェクトの場合、オブジェクトの作成は通常、オブジェクトが明示的に作成されるとき (C++ や Java などで) 明示的に、または変数の有効期間の開始時に暗黙的に、特にオブジェクトのスコープがnew変更されたときに、決定論的に行われます。宣言時などに自動変数が入力されます。 [b]ただし、オブジェクトの破棄はさまざまです。一部の言語、特に C++ では、自動および動的オブジェクトは、スコープの終了、明示的な破棄 (手動メモリ管理による)、参照カウントがゼロになるなど、決定的な時点で破棄されます。一方、C#、Java、Python などの他の言語では、これらのオブジェクトはガベージ コレクターに応じて非決定的なタイミングで破棄され、破棄中にオブジェクトの復活が発生して寿命が延びる場合があります。

ガベージ コレクション言語では、オブジェクトは通常、(スタック上またはレジスタ内で) 自動的に割り当てられるプリミティブ値を持つ自動変数とは異なり、最初に自動変数にバインドされている場合でも、通常は動的に (ヒープ上で) 割り当てられます。これにより、オブジェクトを破棄せずに関数 (「エスケープ」) から返すことができます。ただし、場合によっては、コンパイラの最適化が可能です。つまり、エスケープ解析を実行し、エスケープが不可能であることを証明することで、オブジェクトをスタックに割り当てることができます。これは Java では重要です。この場合、オブジェクトの破棄は即座に行われます。変数に到達できない場合は、変数の存続期間中 (スコープの終了前) であっても可能です。

複雑なケースは、オブジェクト プールの使用です。この場合、オブジェクトは事前に作成されたり再利用されたりするため、見かけ上の作成と破棄は、オブジェクトの実際の作成と破棄に対応せず、作成のための (再) 初期化とオブジェクトのファイナライズのみに対応する場合があります。破壊。この場合、作成と破棄の両方が非決定的になる可能性があります。

ステップ

オブジェクトの作成は、メモリ割り当て初期化の2 つの操作に分類できます。初期化にはオブジェクト フィールドへの値の割り当てと、場合によっては他の任意のコードの実行が含まれます。これらは実装レベルの概念であり、変数の宣言定義の区別にほぼ似ていますが、後で言語レベルの区別になります。変数に関連付けられたオブジェクトの場合、宣言はメモリ割り当て (オブジェクト用のスペースの予約) にコンパイルされ、定義は初期化 (値の割り当て) にコンパイルされますが、宣言はコンパイラでのみ使用される場合もあります (名前解決など)。コンパイルされたコードには直接対応しません。

同様に、オブジェクトの破棄は、ファイナライゼーションとメモリ割り当て解除という逆の順序の 2 つの操作に分類できますこれらには、変数に対する同様の言語レベルの概念がありません。変数の有効期間は暗黙的に終了し (自動変数の場合はスタックのアンワインド時、静的変数の場合はプログラム終了時)、この時点 (または実装によっては後で) メモリの割り当てが解除されます。ただし、通常はファイナライズは行われません。ただし、オブジェクトの有効期間が変数の有効期間に関連付けられている場合、変数の有効期間が終了すると、オブジェクトがファイナライズされます。これは C++ の標準パラダイムです。

これらを組み合わせると、次の 4 つの実装レベルのステップが生成されます。

割り当て、初期化、終了処理、割り当て解除

これらのステップは、言語ランタイム、インタプリタ、または仮想マシンによって自動的に実行される場合もあれば、プログラマーによってサブルーチン (具体的にはメソッド経由) で手動で指定される場合もあります。この頻度はステップや言語によって大きく異なります。クラスベースの言語では、初期化はプログラマによって指定されるのが非常に一般的ですが、厳密なプロトタイプベースの言語では、初期化はコピーによって自動的に行われます。ファイナライゼーションは、決定論的破壊を行う言語、特に C++ では非常に一般的ですが、ガベージ コレクション言語ではあまり一般的ではありません。割り当てが指定されることはほとんどなく、通常、割り当て解除は指定できません。

作成時と破棄時のステータス

重要な点は、作成または破棄中のオブジェクトのステータスと、作成または破棄が失敗した場合など、エラーが発生したり例外が発生した場合の処理​​です。厳密に言えば、オブジェクトの存続期間は割り当てが完了したときに始まり、割り当て解除が開始されたときに終了します。したがって、初期化と終了中、オブジェクトは生きていますが、一貫性のある状態ではない可能性があります。クラスの不変条件を確保することが初期化の重要な部分です。また、初期化が完了してから終了処理が開始されるまでの期間が、オブジェクトが生きていて期待される期間となります。一貫した状態にあること。

作成または破棄が失敗した場合、エラー報告 (多くの場合、例外が発生することによる) が複雑になる可能性があります。オブジェクトまたは関連オブジェクトが不整合な状態にある可能性があり、破棄の場合 (通常は暗黙的に発生するため、不特定の環境で発生します)エラーの処理が難しい場合があります。反対の問題は、発信例外ではなく受信例外ですが、異なる動作が必要な場合に、例外処理中に発生した場合に作成または破棄を異なる動作にする必要があるかどうかです。

もう 1 つの微妙な点は、静的変数の作成と破棄がいつ行われるです。静的変数の寿命はプログラムの実行時間と一致します。作成と破棄は通常のプログラムの実行中に行われるのか、それとも通常の実行の前後の特別なフェーズで行われるのか、また、プログラム時にオブジェクトがどのように破棄されるのかということです。プログラムが通常の状態または一貫した状態にない可能性がある場合の終了。プログラムの終了時に大量のガベージが発生する可能性があるため、これはガベージ コレクション言語の場合に特に問題になります。

クラスベースのプログラミング

クラスベース プログラミングでは、オブジェクトの作成はインスタンス化(クラスインスタンスの作成)とも呼ばれ、作成と破棄は、コンストラクターデストラクターまたはイニシャライザーファイナライザーとして知られるメソッドを介して制御できます。したがって、作成と破棄は構築破棄とも呼ばれ、これらのメソッドが呼び出されるとき、オブジェクトは構築される破棄される(「破棄」ではない)と言われ、それぞれ、これらのメソッドが呼び出されたときに 初期化または終了されます。

これらのメソッド間の関係は複雑になる場合があり、言語にはコンストラクターとイニシャライザーの両方 (Python など)、またはデストラクターとファイナライザーの両方 ( C++/CLIなど) が含まれる場合があり、「デストラクター」と「ファイナライザー」という用語は言語を指す場合もあります。レベル構成と実装 (C# と CLI のような)。

主な違いは、オブジェクトが作成されるまでは使用可能なオブジェクト (クラス インスタンス) がないため、コンストラクターはクラス メソッドであるのに対し、他のメソッド (デストラクター、イニシャライザー、およびファイナライザー) は、オブジェクトが作成されるとインスタンス メソッドであるということです。さらに、コンストラクターとイニシャライザーは引数を取ることができますが、デストラクターとファイナライザーは通常暗黙的に呼び出されるため、通常は引数を受け取りません。

一般的な使用法では、コンストラクターは、オブジェクトを作成するためにユーザー コードによって直接呼び出されるメソッドです。一方、「デストラクター」は、オブジェクトの有効期間が決定的な言語でオブジェクトの破棄時に (通常は暗黙的に、場合によっては明示的に) 呼び出されるサブルーチンです。アーキタイプは C++ です。 – そして、「ファイナライザー」は、オブジェクトの有効期間が非決定的な言語でオブジェクトを破棄する際に、ガベージ コレクターによって暗黙的に呼び出されるサブルーチンです。原型は Java です。

ファイナライズ中の手順はメモリ管理によって大幅に異なります。手動メモリ管理 (C++ や手動参照カウントなど) では、プログラマが参照を明示的に破棄する必要があります (参照はクリアされ、参照カウントはデクリメントされます)。自動参照カウントでは、これはファイナライゼーション中にも発生しますが、自動化されます (Python のように、プログラマ指定のファイナライザが呼び出された後に発生します)。ガベージ コレクションのトレースでは、これは必要ありません。したがって、自動参照カウントでは、プログラマ指定のファイナライザが不足しているか、存在しないことがよくありますが、それでも重要な作業が行われる可能性がありますが、ガベージ コレクタのトレースでは、ファイナライゼーションは多くの場合不要です。

資源管理

オブジェクトの有効期間が決定的な言語では、オブジェクトの有効期間がリソース管理に便乗するために使用される場合があります。これは、リソース取得は初期化(RAII) というイディオムと呼ばれます。つまり、リソースは初期化中に取得され、ファイナライズ中に解放されます。特にガベージ コレクションのせいで、オブジェクトの有効期間が非決定的である言語では、メモリの管理は通常、他のリソースの管理から分離されます。

オブジェクトの作成

一般的なケースでは、プロセスは次のとおりです。

  • オブジェクトのサイズを計算します。サイズはクラスのサイズとほぼ同じです、異なる場合があります。問題のオブジェクトがクラスからではなくプロトタイプから派生している場合、オブジェクトのサイズは通常、そのスロットを保持する内部データ構造 (ハッシュなど) のサイズになります。
  • 割り当て – オブジェクトのサイズに、可能であれば事前にわかっている場合は後の増加分を加えたメモリ空間を割り当てます。
  • バインディングメソッド – これは通常、オブジェクトのクラスに任されるか、ディスパッチ時に解決されますが、それでも、一部のオブジェクト モデルは作成時にメソッドをバインドする可能性があります。
  • スーパークラスの初期化コード (つまり、コンストラクター)を呼び出す
  • 作成中のクラスの初期化コードを呼び出す

これらのタスクは一度に完了できますが、未完了のままになる場合があり、タスクの順序が異なる場合があり、いくつかの奇妙な動作を引き起こす可能性があります。たとえば、多重継承では、どの初期化コードを最初に呼び出す必要があるかは、答えるのが難しい質問です。ただし、スーパークラス コンストラクターはサブクラス コンストラクターの前に呼び出す必要があります。

各オブジェクトを配列の要素として作成するのは複雑な問題です。[さらなる説明が必要]一部の言語 (C++ など) では、これをプログラマに任せています。

通常、例外をスローする実装は有効なオブジェクトの状態に依存するため、オブジェクトの作成中に例外を処理することは特に問題になります。たとえば、メモリ上の空き領域の不足によりオブジェクトの割り当てがその前に失敗した場合、例外オブジェクトに新しい領域を割り当てる方法はありません。このため、OO 言語の実装では、リソースの供給が不足している場合でも例外を発生できるメカニズムを提供する必要があり、プログラマまたは型システムはコードが例外安全であることを保証する必要があります。例外を伝播すると、リソースが割り当てられるよりも解放される可能性が高くなります。しかし、オブジェクト指向プログラミングでは、オブジェクトの構築にはクラスの不変条件を確立する必要があるため、オブジェクトの構築が失敗する可能性があります。これは、多くの場合、コンストラクター引数のすべての組み合わせに対して有効ではありません。したがって、コンストラクターは例外を発生させる可能性があります。

抽象ファクトリ パターンは、オブジェクトの特定の実装を、そのようなオブジェクトを作成するコードから分離する方法です。

作成方法

オブジェクトを作成する方法は言語によって異なります。一部のクラスベース言語では、コンストラクターとして知られる特別なメソッドがオブジェクトの状態を検証します。通常のメソッドと同様に、コンストラクターをオーバーロードして、さまざまな属性を指定してオブジェクトを作成できるようにすることができます。また、コンストラクターは不変オブジェクトの状態を設定する唯一の場所です[誤った説明が必要です]。コピーコンストラクターは、コンストラクターのクラスと同じ型の既存のオブジェクトの (単一の) パラメーターを受け取り、パラメーターとして送信されたオブジェクトのコピーを返すコンストラクターです。

Objective-Cなどの他のプログラミング言語にはクラス メソッドがあり、コンストラクター タイプのメソッドを含めることができますが、単にオブジェクトをインスタンス化することに限定されません。

C++Java は[誰によって批判されていますか? ]名前付きコンストラクターを提供しないため、コンストラクターは常にクラスと同じ名前を持つ必要があります。これは、プログラマが同じ引数型を持つ 2 つのコンストラクターを提供したい場合、たとえばデカルト座標または極座標のいずれかから点オブジェクトを作成する場合(どちらも 2 つの浮動小数点数で表される) に問題となる可能性があります。 Objective-C では、プログラマが次のような初期化メソッドを使用して Point クラスを作成できるため、この問題を回避できます。+newPointWithX:and


gg\gY:、 そして+newPointWithR:andTheta:。 C++ では、静的メンバー関数を使用して同様のことを実行できます。[1]

コンストラクターは、特に関数型言語で、 タグ付き Unionの値を作成するために使用される関数を参照することもできます。

オブジェクトの破壊

一般に、オブジェクトが使用された後、そのオブジェクトの代わりに他のプログラムまたはオブジェクトが使用できるスペースを確保するために、そのオブジェクトはメモリから削除されます。ただし、十分なメモリがある場合、またはプログラムの実行時間が短い場合は、オブジェクトの破棄は発生せず、プロセス終了時にメモリの割り当てが解除されるだけである可能性があります。場合によっては、特にガベージ コレクション言語の場合、または「オブジェクト」が実際には単純な古いデータ構造である場合、オブジェクトの破棄は単純にメモリの割り当てを解除するだけで構成されます。他の場合には、割り当て解除の前にいくつかの作業、特にメンバー オブジェクトの破棄 (手動メモリ管理の場合)、またはオブジェクトから他のオブジェクトへの参照を削除して参照カウントを減分する (参照カウントの場合) が実行される場合があります。これは自動的に行われる場合もあれば、オブジェクトに対して特別な破棄メソッドが呼び出される場合もあります。

オブジェクトの有効期間が決定的なクラスベースの言語、特に C++ では、デストラクターは、クラスのインスタンスが削除されたときに、メモリの割り当てが解除される前に呼び出されるメソッドです。 C++ では、デストラクターはさまざまな点でコンストラクターとは異なります。オーバーロードできないこと、引数を持たないこと、クラスの不変条件を維持する必要がないこと、例外をスローした場合にプログラムが終了する可能性があることなどです。

ガベージ コレクション言語では、実行中のコードがオブジェクトに到達できなくなると、オブジェクトが破棄されることがあります。クラスベースの GC 言語では、デストラクターの類似物はファイナライザーであり、オブジェクトがガベージ コレクションされる前に呼び出されます。これらの違いは、ガベージ コレクションは予測不可能であり、C++ デストラクターに比べて使用頻度も大幅に低く、複雑性も低いため、予測不可能な時間と予測不可能な順序で実行されるという点です。このような言語の例には、JavaPythonRuby などがあります。

オブジェクトを破棄すると、そのオブジェクトへの参照が無効になり、手動メモリ管理では既存の参照がダングリング参照になります。ガベージ コレクション (トレース ガベージ コレクションと参照カウントの両方) では、オブジェクトは参照がない場合にのみ破棄されますが、ファイナライゼーションによりオブジェクトへの新しい参照が作成される可能性があり、ダングリング参照を防ぐためにオブジェクトの復活が発生し、参照が有効なままになります。

C++

class Foo { public : // これらはコンストラクターのプロトタイプ宣言です。Foo ( int x ); Foo ( int x , int y ); // オーバーロードされたコンストラクター。Foo ( const Foo & old ); // コンストラクターをコピーします。~フー(); // デストラクター。};  
 
  
   
         
      
                 


Foo :: Foo ( int x ) { // これは、 // 引数が 1 つのコンストラクターの実装です。 }  
  
  


Foo :: Foo ( int x , int y ) { // これは、 // 2 つの引数を持つコンストラクターの実装です。 }    
  
  


Foo :: Foo ( const Foo & old ) { // これは、 // コピー コンストラクターの実装です。 }   
  
  


Foo ::~ Foo () { // これはデストラクターの実装です。} 
  


int main () { Foo foo ( 14 ); // 最初のコンストラクターを呼び出します。Foo foo2 ( 12 , 16 ); // オーバーロードされたコンストラクターを呼び出します。Foo foo3 ( foo ); // コピーコンストラクターを呼び出します。  
          
      
        

  // デストラクタは逆順で
// ここで自動的に呼び出されます。}  

ジャワ

class  Foo 
{ 
public Foo ( int x ) { // これは// 引数 1 つのコンストラクターの実装です}      
    
        
        
    

    public Foo ( int x , int y ) { // これは// 2 つの引数を持つコンストラクターの実装です}    
    
        
        
    

    public Foo ( Foo old ) { // これは// コピー コンストラクターの実装です}  
    
        
        
    

    public static void main ( String [] args ) { Foo foo = new Foo ( 14 ); // 最初のコンストラクターFooを呼び出しますfoo2 = new Foo ( 12 , 16 ); // オーバーロードされたコンストラクターFooを呼び出しますfoo3 = new Foo ( foo ); // コピー コンストラクターを呼び出します// ガベージ コレクションは内部で行われ、オブジェクトは破棄されます} }    
    
             
              
             
        
    

C#

名前空間ObjectLifeTime ; 

class Foo { public Foo () { // これは、 // デフォルトのコンストラクターの実装です。 } 

     
    
        
        
    

    public Foo ( int x ) { // これは、 // 引数が 1 つのコンストラクターの実装です。 } ~ Foo () { // これは// デストラクターの実装です。 }  
    
        
        
    
     
    
        
        
    

    public Foo ( int x , int y ) { // これは、 // 2 つの引数を持つコンストラクターの実装です。 } public Foo ( Foo old ) { // これは、 // コピー コンストラクターの実装です。 public static void Main ( string [] args ) { var defaultfoo = new Foo () ; // デフォルトのコンストラクターを呼び出しますvar foo = new Foo ( 14 ); // 最初のコンストラクターを呼び出しますvar foo2 = new Foo ( 12 , 16 ); // オーバーロードされたコンストラクターを呼び出しますvar foo3 = new Foo ( foo ); // コピー コンストラクターを呼び出します} }    
    
        
        
    
 
      
    
        
        
    
 
        
    
             
             
              
             
    

目的-C

#import <objc/Object.h>

@interface  Point  :オブジェクト
{ 
double x ;ダブルy ; }    
    


//これらはクラスメソッドです。 2 つのコンストラクター
+  ( Point * ) newWithX: ( double ) andY : ( double );を宣言しました。+ (ポイント* ) newWithR: ( double ) andTheta : ( double );     
      

//インスタンスメソッド
-  ( Point * ) setFirstCoord: ( double ); - (ポイント* ) setSecondCoord: ( double );   
    

/* Point は汎用 Object クラスのサブクラスであるため
、 * 汎用割り当ておよび初期化
メソッド、+alloc および -init を既に取得しています。特定のコンストラクターについては
、 * 継承したこれらのメソッドから作成できます

*/ 
@end 
@implementationポイント 
 

-  (ポイント* ) setFirstCoord: ( double ) new_val { x = new_val ; }    

     


-  (ポイント* ) setSecondCoord: ( double ) new_val { y = new_val ; }    

     


+  ( Point * ) newWithX: ( double ) x_val andY: ( double ) y_val { //自動的に割り当てて、 // 特定の初期化を実行するためのクラス メソッドを簡潔に記述しますreturn [[[ポイント割り当て] setFirstCoord : x_val ] setSecondCoord : y_val ]; }       

   
   
        


+  ( Point * ) newWithR: ( double ) r_val andTheta: ( double ) theta_val { //上記と同じことを実行する代わりに、//前のメソッドの同じ結果をこっそり使用できますreturn [ Point newWithX : r_val andY : theta_val ]; }       

   
   
      


@終わり

int 
main ( void ) 
{ 
//2 つの点 p と q を構築します。ポイント* p = [ポイントnewWithX : 4.0 andY : 5.0 ];ポイント* q = [ポイントnewWithR : 1.0 andTheta : 2.28 ];   
        
        

   //...プログラム テキスト.... 
//p は終わりました、それでは解放してください。 //p がそれ自体により多くのメモリを割り当てる場合、 // p のメモリを再帰的に解放するために、オブジェクトの free メソッドをオーバーライドする必要があるかもしれません。しかし、そうではないので、単に[ p free ] にすることができます。   
   
   
   
   
    

   //...その他のテキスト...

   [ q無料]; 

   0を返します} 

オブジェクト パスカル

関連言語: 「Delphi」、「Free Pascal」、「Mac Pascal」。

プログラム; 

タイプ

  DimensionEnum = ( deUnassigned de2D de3D de4D ) ; 
    
      
      
      
      
    

  PointClass =クラスプライベートディメンション: DimensionEnum ;  
  
     

  パブリック
X :整数; Y :整数Z :整数; T :整数;     
     
     
     

  public 
(* コンストラクターのプロトタイプ *)    

    コンストラクターCreate () ;コンストラクターCreate ( AX , AY : Integer ) ;コンストラクターCreate ( AX AY AZ :整数) ;コンストラクターCreate ( AX AY AZ ATime : Integer ) ;コンストラクターCreateCopy ( APoint : PointClass ) ; 
       
        
         
      

    (* デストラクターのプロトタイプ *)

    デストラクタ破壊します終わり; 
  

コンストラクターPointClass 作成する(); begin // ジェネリックな非引数コンストラクターSelfの実装ディメンション:=割り当て解除;終わり; 

  
    


コンストラクターPointClass 作成( AX , AY :整数) ; begin // 2 引数のコンストラクターSelfの実装X := AX ; Y := AY ;   

  
    
    

  セルフ次元:= de2D ;終わり;  


コンストラクターPointClass 作成( AX AY AZ :整数) ; begin // 3 引数のコンストラクターSelfの実装X := AX ; Y := AY ;セルフX := AZ ;    

  
    
    
    

  セルフ寸法:= de3D ;終わり;  


コンストラクターPointClass Create ( AX AY AZ ATime :整数) ; begin // 4 引数のコンストラクターSelfの実装X := AX ; Y := AY ;セルフX := AZ ; T := A 時間;     

  
    
    
    
    

  セルフディメンション:= de4D ;終わり;  


コンストラクターPointClass CreateCopy ( APoint : PointClass ) ; begin // "コピー" コンストラクターAPointの実装X := AX ;点数Y := AY ;点数X := AZ ;点数T := A 時間;  

  
    
    
    
    

  セルフディメンション:= de4D ;終わり;  


デストラクターPointClass ポイントクラス破壊する; begin // ジェネリックな非引数デストラクタSelfの実装ディメンション:= deUnAssigned ;終わり; 

  
    


var 
(* 静的割り当て用の変数 *) S : PointClass ; (* 動的割り当て用の変数 *) D : ^ PointClass ;  
    
  
   

begin (* プログラムの *) (* 静的割り当てによるオブジェクトのライフライン *) S . ( 5 , 7 )を作成します 
  
   

  (* "S" で何かをする *)

  S .破壊する; 

  (* 動的割り当てを使用したオブジェクト ライフライン *) 
D = new PointClass , Create ( 5 , 7 ) ;       

  (* "D" で何かをする *)

  破棄D 破壊します終わり(*番組の*)  
  

パイソン

class  Socket : 
    def  __init__ ( self ,  remote_host :  str )  ->  None : 
        # リモートホストに接続します

    def  send ( self ): 
        # データを送信

    def  recv ( self ): 
        # データを受信する
        
    def  close ( self ): 
        # ソケットを閉じる
        
    def  __del__ ( self ): 
        # オブジェクトの参照カウントがゼロのときに呼び出される __del__ マジック関数
        self 近い()

def  f ():
    ソケット =  Socket ( "example.com" )
    ソケットsend ( "test" )
    ソケットを返します 受信()

ソケットへの参照はすべて失われているため、「f」関数が実行されて戻った後、次のガベージ コレクション ラウンドでソケットが閉じられます。

こちらも参照

ノート

  1. ^ さまざまな微妙な点があります。たとえば、C++ では、静的ローカル変数は関数が最初に呼び出されたときに決定的に作成されますが、破棄は非決定的です。
  2. ^ C++ では、静的ローカル変数の作成は、実行が 初めて宣言に到達したときに、同様の方法で決定的に行われます

参考文献

  1. ^ C++ FAQ: 「名前付きコンストラクター イディオム」とは何ですか?
「https://en.wikipedia.org/w/index.php?title=オブジェクトの寿命&oldid=1211548519#オブジェクトの作成」から取得