所有権とムーブ

変数は所有するリソースを開放する必要があるため、 リソースは一つの所有者 しか持ちません。リソースを2度以上開放しないためでもあります。すべての変数 がリソースを持つわけではないことに注意してください(例えば参照)。

変数に値を代入(let x = y)したときや、関数に値を渡した(foo(x))とき、 リソースの所有権が渡されます。これをRustでは、ムーブと呼んでいます。

リソースをムーブしたら、元の所有者はもうそのリソースを使うことができません。 これによって、危険なポインタを作成するのを防ぎます。

// ヒープに確保したメモリの所有権を必要とする関数
fn destroy_box(c: Box<i32>) {
    println!("Destroying a box that contains {}", c);

    // `c`は破棄され、メモリが開放される
}

fn main() {
    // _スタック_に整数を確保する
    let x = 5u32;

    // `x`を`y`に*コピー*する。所有権はムーブされない
    let y = x;

    // どちらの値も独立して使える
    println!("x is {}, and y is {}", x, y);

    // `a`は_ヒープ_に確保した整数のポインタ
    let a = Box::new(5i32);

    println!("a contains: {}", a);

    // `a`を`b`に*ムーブ*する
    let b = a;
    // `a`のポインタアドレスは`b`にコピーされる。
    // どちらも同じヒープのポインタをもつが、現在
    // `b`が所有している。
    
    // エラー! `a`はヒープメモリのデータを所有していないため、
    // データを使用できない。
    //println!("a contains: {}", a);
    // TODO ^ この行をアンコメントしてみてください

    // `b`が持っているメモリの所有権を取る関数
    destroy_box(b);

    // ここでヒープメモリは開放されたので、開放されたメモリのポインタを
    // 使うことになるが、これはコンパイラによって禁止されている。
    // エラー! 前のエラーと同じ理由
    //println!("b contains: {}", b);
    // TODO ^ この行をアンコメントしてみてください
}