Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

配列とスライス

配列は、同じ型 T のオブジェクトのコレクションであり、連続した メモリに格納されます。配列はブラケット [] を使って作成され、その長さは コンパイル時に既知であり、型シグネチャ [T; length] の一部です。

スライスは配列に似ていますが、その長さはコンパイル時にはわかりません。 代わりに、スライスは 2 ワードのオブジェクトです。最初のワードはデータへのポインター、 2 番目のワードはスライスの長さです。ワードサイズは usize と同じで、 プロセッサーアーキテクチャによって決まります。たとえば、x86-64 では 64 ビットです。スライスは 配列の一部を借用するために使用でき、型シグネチャは &[T] です。

use std::mem;

// この関数はスライスを借用します。
fn analyze_slice(slice: &[i32]) {
    println!("スライスの最初の要素: {}", slice[0]);
    println!("スライスには {} 個の要素があります", slice.len());
}

fn main() {
    // 固定長配列(型シグネチャは冗長です)。
    let xs: [i32; 5] = [1, 2, 3, 4, 5];

    // すべての要素を同じ値で初期化できます。
    let ys: [i32; 500] = [0; 500];

    // インデックスは 0 から始まります。
    println!("配列の最初の要素: {}", xs[0]);
    println!("配列の 2 番目の要素: {}", xs[1]);

    // `len` は配列内の要素数を返します。
    println!("配列内の要素数: {}", xs.len());

    // 配列はスタックに割り当てられます。
    println!("配列は {} バイトを占有します", mem::size_of_val(&xs));

    // 配列はスライスとして自動的に借用できます。
    println!("配列全体をスライスとして借用します。");
    analyze_slice(&xs);

    // スライスは配列の一部を指すことができます。
    // 形式は [starting_index..ending_index] です。
    // `starting_index` はスライス内の最初の位置です。
    // `ending_index` はスライス内の最後の位置より 1 つ大きい値です。
    println!("配列の一部をスライスとして借用します。");
    analyze_slice(&ys[1 .. 4]);

    // 空のスライス `&[]` の例:
    let empty_array: [u32; 0] = [];
    assert_eq!(&empty_array, &[]);
    assert_eq!(&empty_array, &[][..]); // 同じですが、より冗長です

    // 配列は `.get` を使って安全にアクセスできます。これは
    // `Option` を返します。以下に示すようにマッチさせることも、
    // プログラムをそのまま続行させる代わりに、適切なメッセージ付きで
    // 終了させたい場合は `.expect()` とともに使用することもできます。
    for i in 0..xs.len() + 1 { // おっと、1 要素分行き過ぎです!
        match xs.get(i) {
            Some(xval) => println!("{}: {}", i, xval),
            None => println!("ゆっくり進んでください!{} は遠すぎます!", i),
        }
    }

    // 定数値で配列を範囲外インデックス指定すると、コンパイル時エラーが発生します。
    //println!("{}", xs[5]);
    // スライスを範囲外インデックス指定すると、実行時エラーが発生します。
    //println!("{}", xs[..][5]);
}