Difference between revisions of "Dynamic array/ja"
Miyatakejiro (talk | contribs) |
m (Fixed syntax highlighting) |
||
(10 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
{{Dynamic array}} | {{Dynamic array}} | ||
− | 動的配列は、 FreePascal ( と Delphi) のとても便利な機能です。それは、 [[ | + | 動的配列は、 FreePascal ( と Delphi) のとても便利な機能です。それは、 [[Array/ja|配列]] 型ととてもよく似ていますが、プログラムの実行時以前に要素数を決める必要がないことから、プログラマーにより高い柔軟性をもたらします。 |
− | + | 宣言部は、[[Array/ja|配列]] 型においても大変シンプルな記述となっています。: | |
− | <syntaxhighlight> | + | <syntaxhighlight lang=pascal> |
var | var | ||
... | ... | ||
Line 13: | Line 13: | ||
要素の数は、 SetLength 宣言を挿入することで、プログラムの実行中に、いつでも必要に応じて設定することができます。: | 要素の数は、 SetLength 宣言を挿入することで、プログラムの実行中に、いつでも必要に応じて設定することができます。: | ||
− | <syntaxhighlight> | + | <syntaxhighlight lang=pascal> |
begin | begin | ||
... | ... | ||
Line 20: | Line 20: | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | '''SetLength''' 宣言は、配列を拡大したり切り詰めたりするために、プログラム中で何回でも、どの位置でも宣言できますが、初めて配列を用いる前に、少なくとも1回は宣言する必要があります。 | |
個々の要素へのアクセスは、以下のようにして行います。: | 個々の要素へのアクセスは、以下のようにして行います。: | ||
− | <syntaxhighlight> | + | <syntaxhighlight lang=pascal> |
... | ... | ||
SetLength(MyVariable,19); | SetLength(MyVariable,19); | ||
Line 37: | Line 37: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | 動的配列のインデックスは、0「ゼロ」が下限となります。すなわち、範囲は 0 から (Length-1)までとなります。 これを、1「イチ」 がインデックスの下限になるようには、できません。 | |
− | + | 実際には、動的配列は自動的に再参照(automatic dereferencing)を行うポインタです。 それらは、自動的に '''nil''' に初期化されます。 これは、 変数 '''MyVariable''' を '''fillchar''', '''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つの配列は各要素がお互いに独立した配列となります。 | |
== 関連情報 == | == 関連情報 == |
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 に初期化されます。 これは、 変数 MyVariable を fillchar, 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つの配列は各要素がお互いに独立した配列となります。