• 所有权和移动

    所有权和移动

    因为变量要负责释放它们拥有的资源,所以资源只能拥有一个所有者。这也防止了资源的重复释放。注意并非所有变量都拥有资源(例如 references)。

    在进行赋值(let x = y)或通过值来传递函数参数的时候,资源的所有权ownership)会发生转移(transfer)。按照 Rust 的说法,这种方式被称为移动move)。

    在移动资源之后,原来的所有者不能再使用,这可避免悬垂指针的产生。

    1. // 此函数取倒堆分配的内存的所有权
    2. fn destroy_box(c: Box<i32>) {
    3. println!("Destroying a box that contains {}", c);
    4. // `c` 被销毁且内存得到释放
    5. }
    6. fn main() {
    7. // 栈分配的整型
    8. let x = 5u32;
    9. // 将 `x` **复制**(*Copy*)到 `y`——不存在资源移动
    10. let y = x;
    11. // 两个值都可以独立地使用
    12. println!("x is {}, and y is {}", x, y);
    13. // `a` 是一个指向堆分配的整型的指针
    14. let a = Box::new(5i32);
    15. println!("a contains: {}", a);
    16. // **移动**(*Move*) `a` 到 `b`
    17. let b = a;
    18. // 把 `a` 的指针地址(非数据)复制到 `b`。现在两者都是指向
    19. // 同一个堆分配的数据,但是现在是 `b` 占有它。
    20. // 报错!`a` 再也不能访问数据,因为它不再拥有堆上的内存。
    21. //println!("a contains: {}", a);
    22. // 试一试 ^ 将此行注释去掉
    23. // 此函数从 `b` 中取得栈分配的内存的所有权
    24. destroy_box(b);
    25. // 此时堆上的内存已经释放掉,而这个操作会导致解引用已释放的内存,
    26. // 但这种情况会被编译器会禁止。
    27. // 报错!和前面出错的原因一样。
    28. //println!("b contains: {}", b);
    29. // 试一试 ^ 将此行注释去掉
    30. }