规则

  • 每个值都有一个变量叫做所有者(owner)
  • 同一时间只能有一个所有者
  • 当所有者超出作用域则值被销毁

变量作用域

  • 作用域是一个变量有效的范围
  • 当变量超出作用域范围自动调用对象的 drop 方法进行内存归还操作

变量相互作用:所有权转移(Move)

对于所有在栈上分配的值(固定大小),在进行赋值操作时都对值进行拷贝:

let x = 5;
ley y = x;  // copy 5 to y

但是对于在堆上分配的,变量保存的是指向内存的指针,所以在赋值时拷贝的也是指向该内存的指针:

let s1 = String::from("hello");
let s2 = s1;

为了保证内存安全,防止 s1s2 超出作用域范围调用两次 drop 造成重复的内存回收,Rust 会让 s1 不再有效,来避免对 s1 进行回收。继续使用 s1 会导致编译错误。这种情况叫做所有权转移(move)。

变量相互作用:克隆(Clone)

克隆用于深度拷贝变量:

let s1 = String::from("hello");
let s2 = s1.clone();
println!(s1);

变量项目作用:拷贝(Copy)

如果数据类型的大小在编译期能够确定都将存储在栈上,这种情况下能够进行快速的拷贝。

  • Copy 特性(trait)注解用于将值存贮在栈栈上
  • Copy 特性注解不能和 Drop 特性注解混用
  • Copy 特性注解使用规则如下
    • 所有的数字类型
    • 所有的布尔型
    • 所有的浮点型
    • 字符类型
    • 所有元素都实现了 Copy 特性注解的元祖

所有权和函数

函数传递实参的规则和变量类似,传递变量到一个函数将为发生所有权转移或者拷贝。

返回值和作用域

  • 返回值可以转移所有权
  • 将一个值赋给其他变量会产生所有权转移
  • 一个包含堆分配的变量超出作用域将会被 drop 清理,除非所有权被转移到其他变量。