コンピュータプログラミングにおいて、動的変数は、手動で割り当てられたメモリに格納され、割り当てと解放が可能なローカル変数です。動的変数は、暗黙的ヒープ動的変数、明示的ヒープ動的変数、および失われたヒープ動的変数(ダングリングポインタ)の 3 つのタイプに分類されます。動的変数は、不定のスコープと動的な範囲を持ちます。主に、 Lisp、Ruby、APL、PHP、TcL、TEX、PERLなどのニッチなプログラミング言語で使用されます。[ 1 ]
let l = 10 ; // 暗黙的にヒープメモリに格納される値let b = 20 ; area = l * b ;int main () { int * y = new int ( 1 ); // 動的変数 *y を作成for ( int i = 0 ; i < 5 ; i ++ ) { if ( * y <= 5 ) cout << * y << endl ; ( * y ) ++ ; // ポインタを介して値をインクリメント} delete y ; // メモリリークを防ぐために変数を削除return 0 ; }int * a = new int ( 10 ); // ヒープに割り当て 動的変数a = new int ( 20 ); // メモリを解放せずに同じ変数に再割り当て1950年代後半のLISP言語の開発中、動的メモリ管理の一形態としてガベージコレクションがLISPの自動動的割り当てに使用されました。これは、プログラマが使用済みメモリ領域を手動で削除する代わりに、メモリ管理を自動化することを目的としていました。マークアンドスイープ、参照カウント、コピーアルゴリズムなどのアルゴリズムは、ガベージコレクションの概念の基礎となりました。これらのアルゴリズムはジョン・マッカーシーによって開発されましたが、マッカーシーとマービン・ミンスキーの両方がLISPの開発における重要人物でした。[ 2 ]
以前の動的変数の概念は、変数割り当てにヒープとスタックの両方の割り当てがあったALGOL 68で使用されていました。ポインタ型とヒープ割り当ての限定的なガベージコレクションも使用されていました。[ 3 ]
1968~69年に設計された動的変数は、 1970年にニクラウス・ヴィルトによって開発されたプログラミング言語Pascalで初めて命名および定義され、参照される変数のメモリを格納するポインタとして記述される変数が定義されました。ポインタへのメモリの割り当てはコマンドによって行われ、メモリの解放はコマンドによって行われました。[ 4 ]NEWDISPOSE
動的オブジェクト、ポインタ、およびさまざまなプログラミング言語におけるさまざまな種類の動的変数については、1989 年に Robert Sebesta が著した書籍「Concepts of Programming Languages」で初めて詳細に説明されました。[ 5 ]
これらの変数では、アセンブリではなく実行時にアドレスが決定される間接アドレッシングモードが使用されます。スタックベースの動的変数では、スタックポインタ(SP)とフレームポインタ(FP)を使用するスタックアドレッシングモードが使用されます。プッシュ操作中はSPが上に移動し、ポップ操作中はSPが下に移動します。FPはオフセット参照として機能し、そこからSPが計算されます。これらのアドレッシングモードはどちらもx86コンピュータアーキテクチャで使用されます。
スコープ(コンピュータプログラミング)と変数の範囲に関して言えば、動的変数は静的変数(グローバル)とは異なりローカルです。つまり、動的変数は定義された関数内でのみ使用でき、異なる値で再利用するにはメモリの解放と再割り当てが必要になります。動的変数の寿命はプログラマによって制御されます。動的変数へのメモリ割り当ては実行時に行われます。メモリリークを防ぐため、動的変数は再利用する前に必ず解放する必要があります。
簡単に言うと、動的変数はスコープが不定で、プログラム内で使用されるどのコードからも変数のバインディングを参照できます。また、動的範囲は、変数のバインディングが作成時から、実行中に動的変数を使用するコードから制御が離れるまでの間のみ参照できることを意味します。したがって、Pythonでは作成されるすべての変数がグローバルまたはレキシカルスコープであるため、動的変数を参照することはできません。
動的オブジェクトは、使用するオブジェクトの数が不明な場合にメインメソッドで作成され、動的メモリ割り当てを可能にすることで静的オブジェクトよりも柔軟性が高くなります。以下のコードスニペットでは、動的オブジェクトが作成されるとコンストラクタクラスがCounter自動的に呼び出され*c、値5が割り当てられます。deleteオブジェクトを制御すると、デストラクタ~Counterが呼び出され、出力が表示されます。
class Counter { int value ; public : Counter ( int start ) { // オブジェクトの初期化時に呼び出されるコンストラクタvalue = start ; }~ Counter () { // オブジェクトが破棄されたときにデストラクタが呼び出されますvalue -- ; cout << value ; // 4 が出力されます} };int main () { Counter * c = new Counter ( 5 ); delete c ; return 0 ; }