配列を初期化する各種の方法について。
全ての要素の値を指定する。
fn main() {
let arr = [0, 1, 2];
assert_eq!(arr, [0, 1, 2]);
}
Default
トレイトの利用
既定値で全要素を初期化する。
この方法は const
や static
で宣言する配列には使用できない。
fn main() {
let arr = <[i32; 3] as Default>::default();
assert_eq!(arr, [0, 0, 0]);
}
Copy
トレイトの利用
指定値のコピーで全要素を初期化する。
fn main() {
let arr = [42; 3];
assert_eq!(arr, [42, 42, 42]);
}
const
キーワードの利用
const
宣言した変数や const
ブロック式の値で全要素を初期化する。
Vec::<i32>::new()
なども値として指定可能 (Vec::new
が const
関数のため)。
以下では、『Copy トレイトの利用』との差別化のため要素型 CopyNg
を用いている。
fn main() {
let arr = [const { CopyNg(42) }; 3];
assert_eq!(arr, [CopyNg(42), CopyNg(42), CopyNg(42)]);
}
#[derive(Debug, Eq, PartialEq)]
struct CopyNg(i32);
array::from_fn
関数の利用
各要素の値をラムダで生成して初期化する。
この方法は const
や static
で宣言する配列には使用できない。
これは array::from_fn
が const
関数でないため。
use std::array;
fn main() {
let arr = array::from_fn::<_, 3, _>(|i| i as i32);
assert_eq!(arr, [0, 1, 2]);
}
既存の配列をラムダで変換して初期化する。
この方法は const
や static
で宣言する配列には使用できない。
これは [T; N]::map
が const
関数でないため。
fn main() {
let arr_src = [0, 1, 2];
let arr = arr_src.map(|x| x + 1);
assert_eq!(arr, [1, 2, 3]);
}
Vec
型の利用
ベクタを配列へと変換する。サイズが合わないとエラーになる。
変換方法は以下の二通りがあり、どちらも同じ結果になる。
この方法は const
や static
で宣言する配列には使用できない。
これは try_from
や try_into
が const
関数でないため。
以下では、try_from
を利用している。
fn main() {
let vec = vec![0, 1, 2];
let arr = <[_; 3]>::try_from(vec).unwrap();
assert_eq!(arr, [0, 1, 2]);
}
以下では、try_into
を利用している。
fn main() {
let vec = vec![0, 1, 2];
let arr: [i32; 3] = vec.try_into().unwrap();
assert_eq!(arr, [0, 1, 2]);
}
MaybeUninit
共用体の利用
未初期化の配列を初期化後、アンセーフ機能で通常の配列へと転用する。
use std::mem::{self, MaybeUninit};
fn main() {
let mut arr = [const { MaybeUninit::<i32>::uninit() }; 3];
let mut i = 0;
while i < arr.len() {
arr[i] = MaybeUninit::new(i as i32);
i += 1;
}
let arr = unsafe { mem::transmute::<_, [i32; 3]>(arr) };
assert_eq!(arr, [0, 1, 2]);
}
配列全体を関数で生成して初期化する。
以下では、簡単にするためこっそりと Copy
トレイトに依存している。
(他の方法と併用すれば、その依存もなくせる。)
fn main() {
const ARR: [i32; 3] = create_arr();
assert_eq!(ARR, [0, 1, 2]);
}
const fn create_arr() -> [i32; 3] {
let mut ret = [0; 3];
let mut i = 0;
while i < ret.len() {
ret[i] = i as i32;
i += 1;
}
ret
}