7.2 Persistent Variables

Last-modified: 2025-03-04 (火) 20:19:57

7.2 永続変数

See keyword: persistent

関数内で永続的であると宣言された変数は、同じ関数への後続の呼び出し間でその内容をメモリ内に保持します。永続変数とグローバル変数の違いは、永続変数は特定の関数のスコープ内でローカルであり、他の場所では表示されないことです。

次の例では、永続変数を使用して、呼び出された回数を出力する関数を作成します。

function count_calls ()
 persistent calls = 0;
 printf ("'count_calls' has been called %d times\n",
         ++calls);
endfunction
for i = 1:3
 count_calls ();
endfor
-| 'count_calls' has been called 1 times
-| 'count_calls' has been called 2 times
-| 'count_calls' has been called 3 times

例に示すように、変数は persistent宣言ステートメントを使用して永続的に宣言できます。次のステートメントはすべて永続宣言です。

persistent a
persistent a b
persistent c = 2
persistent d = 3 e f = 5

永続変数の動作は、C の静的変数の動作と同じです。

永続変数に対する制限の 1 つは、関数の入力引数も出力引数も永続化できないことです。

function y = foo ()
 persistent y = 0;  # Not allowed!
endfunction
foo ()
-| error: can't make function parameter y persistent

グローバル変数と同様に、永続変数は一度しか初期化できません。たとえば、次のコードを実行すると、

persistent pvar = 1
persistent pvar = 2

永続変数の値はpvar2 ではなく 1 です。

永続変数が宣言されていても、特定の値に初期化されていない場合は、空のマトリックスが含まれます。したがって、次の例に示すように、永続変数が空かどうかをチェックして初期化することもできます。

function count_calls ()
 persistent calls;
 if (isempty (calls))
   calls = 0;
 endif
 printf ("'count_calls' has been called %d times\n",
         ++calls);
endfunction

この実装は、 の以前の実装とまったく同じように動作しますcount_calls。

永続変数の値は、明示的にクリアされるまでメモリ内に保持されます。 の実装がcount_calls ディスクに保存されていると仮定すると、次の動作が得られます。

for i = 1:2
 count_calls ();
endfor
-| 'count_calls' has been called 1 times
-| 'count_calls' has been called 2 times
clear
for i = 1:2
 count_calls ();
endfor
-| 'count_calls' has been called 3 times
-| 'count_calls' has been called 4 times
clear all
for i = 1:2
 count_calls ();
endfor
-| 'count_calls' has been called 1 times
-| 'count_calls' has been called 2 times
clear count_calls
for i = 1:2
 count_calls ();
endfor
-| 'count_calls' has been called 1 times
-| 'count_calls' has been called 2 times

つまり、永続変数は、その変数を含む関数が削除されたときにのみメモリから削除されます。関数定義を Octave プロンプトに直接入力すると、関数clear定義全体がメモリから削除されるため、永続変数は簡単なコマンドでクリアされることに注意してください。関数がクリアされても永続変数がメモリから削除されないようにするには、mlock関数を使用する必要があります (関数のロックを参照)。