所有权

Rust 的内存管理模型

  • 所有权是 Rust 的核心概念,Rust 最引以为豪的内存安全就建立在所有权之上
  • 语言的内存管理机制

    • C: malloc + free 手动管理,Bug 制造机
    • 垃圾回收技术,开发者只管申请不用手动释放,GC导致程序性能天生的下降,不适合编写底层程序
    • Rust 采用了中间方案 RAII,兼具 GC 的易用和安全,又有极高的性能

      堆和栈

  • C、Java 的值类型和引用类型

  • 有些语言只有引用类型,比如 Python

    所有权的实际规则

  1. Rust 中每个值都绑定有一个变量,称为该值的所有者
  2. 每个值只有一个所有者,而且每个值都有它的作用域
    1. Rust中,{}就是作用域
    2. 所有权被转交后,就不能用原来的变量访问
  3. 一旦当这个值离开作用域,这个值占用的内存将被回收

    借用

  • 希望使用一个值而不是拥有这个值(在函数调用时特别常见) ```rust // 报错的代码 fn echo(s: String) { println!(“{}”, s); } fn main() { let s = String::from(“Hello”); echo(s); println!(“{}”, s); // 报错:value borrowed here after move }

// 使用借用改良 fn echo(s: &String) { println!(“{}”, s); } fn main() { let s = String::from(“Hello”); echo(&s); println!(“{}”, s); }

  1. <a name="ShBLj"></a>
  2. # 不可变引用和可变引用
  3. - 默认情况,引用不可变
  4. - 需要修改引用的值,使用`&mut`
  5. ```rust
  6. fn echo(s: &String) {
  7. println!("{}", s);
  8. }
  9. fn change(s: &mut String) {
  10. s.push_str(" changed");
  11. }
  12. fn main() {
  13. let mut s = String::from("Hello");
  14. echo(&s);
  15. change(&mut s);
  16. echo(&s);
  17. }

可变引用的规则

  • 同一时间最多只能存在一个可变引用
  • 此规则主要用于防止数据竞争

    1. fn main() {
    2. let mut s = String::from("Hello");
    3. let s1_ref = &mut s;
    4. let s2_ref = &mut s1_ref; // cannot borrow as mutable
    5. println!("{}", s2_ref);
    6. }

    生命周期

  • 绝大多数情况,Rust编译器可以自动推导每个变量的生命周期

  • 但是有时候也需要我们在代码中手动注明生命周期

    生命周期注解

  • 语法:生命周期参数名称必须以撇号'开头

    • 其名称通常为全小写,类似于泛型,其名称非常短
    • 'a是大多数人默认使用的名称
    • 生命周期参数注解位于引用的&之后,并有一个空格来将引用类型与生命周期分隔开
  • 生命周期注解并不改变任何引用的生命周期长短 ```rust // 不加生命周期会报错: expected named lifetime parameter // 因为 -> str 可以是 str1/str2,两者可能有不同生命周期 fn bigger<’a>(str1: &’a str, str2: &’a str) -> &’a str { if str1 > str2 {
    1. str1
    } else {
    1. str2
    } }

fn main() { println!(“{}”, bigger(“a”, “b”)); }

  1. ```rust
  2. #[derive(Debug)]
  3. struct Person<'a> {
  4. name: &'a str,
  5. }
  6. fn main() {
  7. let p = Person { name: "mike" };
  8. println!("{:?}", p);
  9. }