配列を初期化する各種の方法について。

方法 1

各要素を指定

全ての要素の値を指定する。

サンプル


fn main() {
    let arr = [0, 1, 2];
    assert_eq!(arr, [0, 1, 2]);
}

方法 2

Default トレイトの利用

既定値で全要素を初期化する。

定数配列には使用不可

この方法は conststatic で宣言する配列には使用できない。

これは Default::defaultconst 関数でないため。

サンプル


fn main() {
    let arr = <[i32; 3] as Default>::default();
    assert_eq!(arr, [0, 0, 0]);
}

方法 3

Copy トレイトの利用

指定値のコピーで全要素を初期化する。

サンプル


fn main() {
    let arr = [42; 3];
    assert_eq!(arr, [42, 42, 42]);
}

方法 4

const キーワードの利用

const 宣言した変数や const ブロック式の値で全要素を初期化する。

Vec::<i32>::new() なども値として指定可能 (Vec::newconst 関数のため)。

サンプル

以下では、『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);

方法 5

array::from_fn 関数の利用

各要素の値をラムダで生成して初期化する。

定数配列には使用不可

この方法は conststatic で宣言する配列には使用できない。

これは array::from_fnconst 関数でないため。

サンプル


use std::array;

fn main() {
    let arr = array::from_fn::<_, 3, _>(|i| i as i32);
    assert_eq!(arr, [0, 1, 2]);
}

方法 6

[T; N]::map メソッドの利用

既存の配列をラムダで変換して初期化する。

定数配列には使用不可

この方法は conststatic で宣言する配列には使用できない。

これは [T; N]::mapconst 関数でないため。

サンプル


fn main() {
    let arr_src = [0, 1, 2];
    let arr = arr_src.map(|x| x + 1);
    assert_eq!(arr, [1, 2, 3]);
}

方法 7

Vec 型の利用

ベクタを配列へと変換する。サイズが合わないとエラーになる。

変換方法は以下の二通りがあり、どちらも同じ結果になる。

定数配列には使用不可

この方法は conststatic で宣言する配列には使用できない。

これは try_fromtry_intoconst 関数でないため。

サンプル 1

以下では、try_from を利用している。


fn main() {
    let vec = vec![0, 1, 2];
    let arr = <[_; 3]>::try_from(vec).unwrap();
    assert_eq!(arr, [0, 1, 2]);
}

サンプル 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]);
}

方法 8

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]);
}

方法 9

配列全体を関数で作成

配列全体を関数で生成して初期化する。

サンプル

以下では、簡単にするためこっそりと 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
}