所有权

规则

  1. Rust 中的每一个值都有一个被称为其 所有者owner)的变量。
  2. 值有且只有一个所有者。
  3. 当所有者(变量)离开作用域,这个值将被丢弃。

    移动(move)语义

    1. {
    2. let s1 = String::from("haha");
    3. // s1无效了
    4. let s2 = s1;
    5. //基本类型(编译器已知在内存中大小类型)可以直接拷贝赋值
    6. let x = 5;
    7. let y = x;
    8. }//自动调用drop()
    如果一个类型拥有 Copy trait,一个旧的变量在将其赋值给其他变量后仍然可用。Rust 不允许自身或其任何部分实现了 Drop trait 的类型使用 Copy trait。如果我们对其值离开作用域时需要特殊处理的类型使用 Copy 注解,将会出现一个编译时错误。
    这些类型默认实现Copy trait:整型、布尔、浮点数、字符、包含Copy trait类型的元组。
    深拷贝
    1. let s1 = String::from("haha");
    2. let s2 = s1.clone();
    3. println!("s1 = {}, s2 = {}", s1, s2);

块结尾自动调用drop函数释放内存。
RAII(Resource Acquisition Is Initialization 资源获取即初始化

所有权与函数

  1. fn main() {
  2. let s = String::from("haha");
  3. //所有权转移到函数内部,外部不能再使用
  4. take_ownership(s);
  5. //Copy类型,外面还可以使用
  6. let x = 5;
  7. make_copy(x);
  8. }
  9. fn take_ownership(s: String) {
  10. println!("{}", s);
  11. }
  12. fn make_copy(x: i32) {
  13. println!("{}", x);
  14. }

返回值转移所有权

  1. fn main() {
  2. let s1 = give_ownership();
  3. let s2 = String::from("hehe");
  4. let (s3, len) = take_and_give_ownership(s2);
  5. println!("{}", s1);
  6. println!("{}, {}", s3, len);
  7. }
  8. fn take_and_give_ownership(s: String) -> (String, usize) {
  9. let len = s.len();
  10. (s, len)
  11. }
  12. fn give_ownership() -> String {
  13. String::from("haha")
  14. }

引用与借用

引用

  1. fn main() {
  2. let s = String::from("hehe");
  3. //创建引用传递进去
  4. let len = get_len(&s);
  5. println!("{}, {}", s, len);
  6. }
  7. //函数以引用作为参数成为借用(borrowing)
  8. fn get_len(s: &String) -> usize {
  9. s.len()
  10. }

可变引用

悬垂引用(Dangling References)

和悬垂指针类似,Rust会进行静态检查编译报错。下面代码s已经释放,&s会变成悬垂引用。

  1. fn main() {
  2. let r = dangle()
  3. }
  4. fn dangle() -> &String {
  5. let s = String::from("haha");
  6. &s
  7. }

解引用

生命周期