Difference between revisions of "Dynamic array/ja"

From Lazarus wiki
Jump to navigationJump to search
m (Fixed syntax highlighting)
 
(7 intermediate revisions by one other user not shown)
Line 4: Line 4:
  
 
宣言部は、[[Array/ja|配列]] 型においても大変シンプルな記述となっています。:   
 
宣言部は、[[Array/ja|配列]] 型においても大変シンプルな記述となっています。:   
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
var
 
var
 
   ...
 
   ...
Line 13: Line 13:
 
要素の数は、 SetLength 宣言を挿入することで、プログラムの実行中に、いつでも必要に応じて設定することができます。:
 
要素の数は、 SetLength 宣言を挿入することで、プログラムの実行中に、いつでも必要に応じて設定することができます。:
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
begin
 
begin
 
   ...
 
   ...
Line 23: Line 23:
  
 
個々の要素へのアクセスは、以下のようにして行います。:
 
個々の要素へのアクセスは、以下のようにして行います。:
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
...
 
...
 
SetLength(MyVariable,19);
 
SetLength(MyVariable,19);
Line 37: Line 37:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
動的配列のインデックスは、0「ゼロ」が基底となります。すなわち、範囲は 0 から (Length-1)までとなります。これを 1「イチ」 を基底にすることはできません。
+
動的配列のインデックスは、0「ゼロ」が下限となります。すなわち、範囲は 0 から (Length-1)までとなります。 これを、1「イチ」 がインデックスの下限になるようには、できません。
  
実際には、Actually, 動的配列はポインタへの自動的な参照のポインタです。dynamic arrays are pointers with automatic dereferencing. それらは、自動的に '''nil''' に初期化されます。They are initialized to '''nil''' automatically. これは、 '''fillchar''', '''sizeof''',などの低レベルのルーチンを通して扱われるとき、 '''MyVariable''' がポインタ変数として翻訳されることを意味します。 This means, that '''MyVariable''' is interpreted as a pointer variable when handed over to low level routines like '''fillchar''', '''sizeof''', etc. しかし、but it is automatically expanded to '''MyVariable^''' when indexing its elements (as in '''MyVariable[2]''') or when handing it over to routines that expect array types.
+
実際には、動的配列は自動的に再参照(automatic dereferencing)を行うポインタです。 それらは、自動的に '''nil''' に初期化されます。 これは、 変数 '''MyVariable''' '''fillchar''', '''sizeof''',などの低レベルのルーチンを通して扱うとき、ポインタ変数として翻訳されることを意味します。 しかし、その要素をインデックス化する際( in '''MyVariable[2]''' のように)、または、その配列を入出力とするルーチンに渡されるとき、それは自動的に '''MyVariable^''' に展開されます。
  
From a memory management view, dynamic array variables are simple pointers. '''SetLength''' allocates and frees memory on the heap as needed. When used in functions or procedures only the pointer is added to the stack. When the procedure exits, the dynamic array variable is removed and the memory is made available again. In fact, the memory management procedures are inserted in the executable program and the result is totally transparent to the programmer. 
+
メモリー管理の点からは、動的配列は単純なポインタです。 '''SetLength''' がアロケートを行い、また、必要に応じてヒープ上のメモリを解放します。 ファンクションやプロシージャとして扱うときは、ポインタのみがスタックに加えられます。 プロシージャから出るときは、動的配列の値は取り除かれ、メモリーはまた利用できるようになります。 実際には、メモリー管理プロシージャは実行プログラムに挿入されており、その結果として、全体的にプログラマーにとって見通しが良くなっています。
  
Assigning '''nil''' to a dynamic array variable automatically frees the memory where the pointer pointed to. It's identical to '''SetLength(MyVariable, 0)'''. This can have a side effect, if the pointer value is not valid for some reason (i.e., if it was read from disk where it was stored from previous program runs). To init such an invalid pointer you have to use '''FillChar(MyVariable,sizeof(MyVariable), #0)'''.
+
動的配列に '''nil''' をアサインすることは、自動的にポインタが示す位置のメモリーを開放します。 それは、 '''SetLength(MyVariable, 0)''' と一致します。 もしポインタ値がなんらかの理由で妥当(valid)ではなくなったときに(すなわち、以前のプログラムが実行した際に保存された位置に、ディスクから読み込まれたなど)、副作用が起こり値が変化するかもしれません。 このような invalid なポインタを初期化するためには、 '''FillChar(MyVariable,sizeof(MyVariable), #0)''' を使う必要があります。
  
Although writing to elements of dynamic arrays does '''not''' create a new instance of the array (no copy-on-write as it exists for Ansistrings) using '''SetLength''' on such arrays '''does''' create a copy! So if 2 dynamic array variables point to the same array (one has been assigned to the other) they do not do so after using '''SetLength''' on one (or both) of them. After the SetLength() call the two variables are distinct arrays whose elements are independent from each other.
+
動的配列の要素に書き込むことは、配列の新たなインスタンスを '''作りません''' (Ansistrings にある no copy-on-write のように) 、そのような配列に '''SetLength''' を使うことはコピーを '''作ります!''' なので、もし2つの動的配列が同じ配列をポイントしていたなら(一方はほかの配列にアサインされています)、それらの配列は '''SetLength''' を一方(または両方)に用いた後とはふるまいが異なります。 SetLength() 呼び出しのあとでは、2つの配列は各要素がお互いに独立した配列となります。
  
 
== 関連情報 ==
 
== 関連情報 ==

Latest revision as of 08:15, 14 February 2020

English (en) español (es) suomi (fi) français (fr) 日本語 (ja) русский (ru)

動的配列は、 FreePascal ( と Delphi) のとても便利な機能です。それは、 配列 型ととてもよく似ていますが、プログラムの実行時以前に要素数を決める必要がないことから、プログラマーにより高い柔軟性をもたらします。

宣言部は、配列 型においても大変シンプルな記述となっています。:

var
  ...
  MyVariable : array of type;
  ...

要素の数は、 SetLength 宣言を挿入することで、プログラムの実行中に、いつでも必要に応じて設定することができます。:

begin
  ...
  SetLength(MyVariable, ItsNewLength);
  ...
end

SetLength 宣言は、配列を拡大したり切り詰めたりするために、プログラム中で何回でも、どの位置でも宣言できますが、初めて配列を用いる前に、少なくとも1回は宣言する必要があります。

個々の要素へのアクセスは、以下のようにして行います。:

...
SetLength(MyVariable,19);
...
MyVariable[18] := 123;
...
MyOtherVariable := MyVariable[0];
...
WriteLn('MyVariable has ', Length(MyVariable), ' elements');  {should be 19}
...
WriteLn('Its range is ', Low(MyVariable), ' to ', High(MyVariable)); {should be 0 to 18}
...

動的配列のインデックスは、0「ゼロ」が下限となります。すなわち、範囲は 0 から (Length-1)までとなります。 これを、1「イチ」 がインデックスの下限になるようには、できません。

実際には、動的配列は自動的に再参照(automatic dereferencing)を行うポインタです。 それらは、自動的に nil に初期化されます。 これは、 変数 MyVariablefillchar, sizeof,などの低レベルのルーチンを通して扱うとき、ポインタ変数として翻訳されることを意味します。 しかし、その要素をインデックス化する際( in MyVariable[2] のように)、または、その配列を入出力とするルーチンに渡されるとき、それは自動的に MyVariable^ に展開されます。

メモリー管理の点からは、動的配列は単純なポインタです。 SetLength がアロケートを行い、また、必要に応じてヒープ上のメモリを解放します。 ファンクションやプロシージャとして扱うときは、ポインタのみがスタックに加えられます。 プロシージャから出るときは、動的配列の値は取り除かれ、メモリーはまた利用できるようになります。 実際には、メモリー管理プロシージャは実行プログラムに挿入されており、その結果として、全体的にプログラマーにとって見通しが良くなっています。

動的配列に nil をアサインすることは、自動的にポインタが示す位置のメモリーを開放します。 それは、 SetLength(MyVariable, 0) と一致します。 もしポインタ値がなんらかの理由で妥当(valid)ではなくなったときに(すなわち、以前のプログラムが実行した際に保存された位置に、ディスクから読み込まれたなど)、副作用が起こり値が変化するかもしれません。 このような invalid なポインタを初期化するためには、 FillChar(MyVariable,sizeof(MyVariable), #0) を使う必要があります。

動的配列の要素に書き込むことは、配列の新たなインスタンスを 作りません が(Ansistrings にある no copy-on-write のように) 、そのような配列に SetLength を使うことはコピーを 作ります! なので、もし2つの動的配列が同じ配列をポイントしていたなら(一方はほかの配列にアサインされています)、それらの配列は SetLength を一方(または両方)に用いた後とはふるまいが異なります。 SetLength() 呼び出しのあとでは、2つの配列は各要素がお互いに独立した配列となります。

関連情報