[1] 静的配列
静的配列は、C言語と同じで、長さが固定されている配列です。静的配列は次のように宣言します。
要素型[要素数] 変数名;
初期値を与えない場合は、すべての要素が要素型のデフォルト初期値で初期化されます。明示的に配列を初期化する場合、[](ブラケット)で配列リテラルを作ります。配列の途中の要素を飛ばして、要素番号を明示して初期化したい場合、初期値の前に、要素番号と:(コロン)を付けます。
配列の要素へのアクセスの仕方はC言語と全く同じです。これは後述の動的配列にも当てはまります。
import std.stdio;
void main(){
int[5] array = [1,2:3,4,5]; //array[0]=1,array[1]=0,array[2]=3,array[3]=4,array[4]=5
for(int count = 0; count < 5; count++){
writef("%d,",array[count] );
}
writefln();
}
1,0,3,4,5,
► スポイラーを表示
init ……… すべての要素がデフォルト初期値で初期化されたその静的配列型のリテラル
length ……… 配列の要素数
sizeof ……… 配列のバイトサイズ (C言語の sizeof(配列変数)に相当する。)
array.length*array[0].sizeofと同じ
ptr ……… 配列の先頭要素のアドレス
dup ……… 配列内容をコピーした動的配列オブジェクト
idup ……… array.dupの型がimmutableになったもの
sort ……… 配列内容をソートする。
reverse ……… 配列内容を逆順にする。
静的配列は、値型なので、関数の引数にした場合、すべての要素がコピーされて渡されます。これは、C言語とは対照的なポイントですね。
[2] 動的配列
一方で、D言語には組み込みの動的配列が存在します。動的配列型の宣言は、単に要素数がないだけです。
要素型[] 変数名;
明示的に初期化しない場合、要素数0として初期化されます。明示的な初期化の方法は、静的配列と同じです。ところで、動的配列の長さは、lengthプロパティによって決まります。静的配列では、lengthプロパティは変更することは出来ませんが、動的配列では書き換えることが出来ます。
書き換えたときの挙動
書き換え後の配列のほうが長いとき… 延長部分の要素はデフォルト初期化される。場合によっては、領域が再確保される。
書き換え後の配列のほうが短いとき… ただ縮小されるだけ。
C++でいうところの、std::vector::resize とほとんど同じ挙動を示します。
ただし、Dの配列はCOW(コピーonライト)なので、書き換え後の配列が、他の配列参照に影響を与える場合は、必ずバッファを再確保します。
SomeType[] array = new SomeType[X];
動的配列が持っているプロパティ
init ……… array.ptr = null,array.length=0;で初期化された配列変数。
length ……… 配列の要素数 書き換え可能
sizeof ……… 配列変数が占有するバイトサイズ。size_t.sizeof + array.ptr.sizeofに相当
ptr ……… 配列の先頭要素のアドレス
dup ……… 配列内容をコピーした動的配列オブジェクト
idup ……… array.dupの型がimmutableになったもの
sort ……… 配列内容をソートする。
reverse ……… 配列内容を逆順にする。
► スポイラーを表示
先ほどのコードで、配列の要素に一つ一つアクセスするのに、for文を使っていました。C言語ではこれが普通ですが、D言語では、配列の要素を列挙するために、それ専用のループ構文が存在します。それがforeach文です。intの配列arrayを列挙するコードは、次のようになります。
import std.stdio;
void main(){
int[5] array = [1,2,3,4,5];
foreach(int value;array){
writef("%d,",value);
}
writeln();
}
1,2,3,4,5,
要するに、foreach(型名 一時変数名;配列変数){……… という構文です。型名は省略可能です。この場合、配列の要素型から型推論されます。また、一時変数にref修飾をする(型名の前にrefを付ける)ことで、変数を参照で受け取ることが出来ます。当然、ref修飾の場合でも、型推論を行わせることが出来ます。
import std.stdio;
void main(){
int[5] array = [1,2,3,4,5];
foreach(ref value;array){
value *= 2;
}
foreach(value;array){
writef("%d,",value);
}
writeln();
}
2,4,6,8,10,
如何なる場合も、foreach文の中で配列オブジェクト自体を書き換えることは出来ません。例えば、動的配列の長さを変更することは出来ません。
前の記事「データ型と式のプロパティ(1)、typeof演算子」 ←→ 次の記事「配列(2)」