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

所有権とムーブ

変数は自分自身のリソースを解放する責任を負うため、 リソースは所有者を 1 つしか持てません。これにより、リソースが 複数回解放されることを防ぎます。すべての変数が リソースを所有しているわけではないことに注意してください(例: references)。

代入(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 ^ この行をコメント解除してみてください
}