所有权和移动

由于变量负责释放它们自己的资源,资源只能有一个所有者。这可以防止资源被多次释放。请注意,并非所有变量都拥有资源(例如引用)。

当进行赋值(let x = y)或按值传递函数参数(foo(x))时,资源的所有权会被转移。在 Rust 中,这被称为移动(move)。

资源移动后,原所有者将无法再被使用。这避免了悬垂指针的产生。

// 此函数获取堆分配内存的所有权
fn destroy_box(c: Box<i32>) {
    println!("正在销毁一个包含 {} 的 box", c);

    // `c` 被销毁,内存被释放
}

fn main() {
    // **栈**分配的整数
    let x = 5u32;

    // 将 `x` **复制**到 `y` - 没有资源被移动
    let y = x;

    // 两个值可以独立使用
    println!("x 是 {},y 是 {}", x, y);

    // `a` 是指向**堆**分配整数的指针
    let a = Box::new(5i32);

    println!("a 包含:{}", a);

    // 将 `a` **移动**到 `b`
    let b = a;
    // `a` 的指针地址(而非数据)被复制到 `b`
    // 现在两者都指向同一块堆分配的数据
    // 但 `b` 现在拥有它
    
    // 错误!`a` 不再拥有堆内存,因此无法访问数据
    //println!("a 包含:{}", a);
    // TODO ^ 尝试取消此行注释

    // 此函数从 `b` 获取堆分配内存的所有权
    destroy_box(b);

    // 此时堆内存已被释放,这个操作会导致解引用已释放的内存
    // 但编译器禁止这样做
    // 错误!原因与前面的错误相同
    //println!("b 包含:{}", b);
    // TODO ^ 尝试取消此行注释
}