Rust(十五)-智能指针

132 阅读3分钟

相关的概念

  • 指针:一个变量在内存中包含的是一个地址(指向其它数据)
  • Rust中最常见的指针就是“引用”
  • 引用:
    • 使用&
    • 借用它指向的值
    • 没有其余开销

智能指针

  • 智能指针是这样的一些数据结构:
    • 行为和指针类似
    • 有额外的元数据和功能
  • 引用计数(reference counting)智能指针类型
    • 通过记录所有者的数量,使一份数据被多个所有者同时持有
    • 并在没有任何所有者时自动清理数据
  • 引用和智能指针的其它不同
    • 引用: 只借用数据
    • 智能指针: 很多时候都拥有它所指向的数据
  • 智能指针的例子
    • string和 vec
    • 都拥有一片内在区域,且允许用户对其操作
    • 还拥有元数据(例如容量等)
    • 提供额外的功能或保障(string保障其数据是合法的utf-8编码)
  • 智能指针的实现
    • 智能指针通常使用struct实现,并且实现了:
      • deref 和 drop这两个trait
    • deref trait: 允许智能指针struct的实例像引用一样使用
    • drop trait:允许你自定义当智能指针实例走出作用域时的代码

本章内容

  • 介绍标准库常见的智能指针
    • Box: 在heap内在上分配值
    • Rc: 启用多重所有权的引用计数类型
    • Ref和refmut,通过Refcell访问:在运行时而不是编译时强制借用规则的类型
  • 此外:
    • 内部可变模式(interior mutability pattern):不可变类型暴露出可修改其内部值的api
    • 引用循环(reference cycles):它们如何泄露内在,以及如何防止其发生。

使用Box来指向Heap上的数据

  • Box
    • 最简单的智能针指针
      • 允许你在heap上存储数据(而不是stack)
      • stack上是指向heap数据的指针
      • 没有性能开销
      • 没有其它额外功能
      • 实现了deref trait 和 drop trait
    • 常用场景
      • 在编译时,某类型的大小无法确定。但使用该类型时,上下文却需要知道它的确切大小。
      • 当你有大量数据,想移交所有权,但需要确保在操作时数据不会被复制
      • 使用某个值时,你只关心它是否实现了特定的trait,而不关心它的具体类型
      fn main() {
          let b = Box::new(5);
          println!("b = {}", b);
      }
      
    • 使用box赋能递归类型
      • 在编译时,Rust需要知道一个类型所占的空间大小
      • 而递归类型的大小无法在编译时确定
      • 但Box类型的大小确定
      • 在递归类型中使用Box就可解决上述问题
      • 函数式语言中的Cons List
    • 关于 Cons List
      • Cons List 是来自Lisp语言的一种数据结构
      • Cons List 里每个成员由两个元素组成
        • 当前项的值
        • 下一个元素
      • Cons List里最后一个成员只包含Nil值,没有下一个元素
    • Cons List不是最常用的集合
      • Vec 是更好的选择
      • 创建一个Cons List
      enum List {
          Cons(i32, List),
          Nil,
      }
      
      fn main() {}
          enum Message {
          Quit,
          Move { x: i32, y: i32 },
          Write(String),
          ChangeColor(i32, i32, i32),
      }
      
      fn main() {}
      
      
  • 使用Box来获得确定大小的递归类型
    • Box是一个指针,Rust知道它需要多少空间,因为:
      • 指针的大小不会基于它指向的数据的大小变化而变化
    • Box
      • 只提供了“间接”存储和heap内存分配的功能
      • 没有其它额外功能
      • 没有性能开销
      • 适用于需要“间接”存储的场景,例如Cons List
      • 实现了Deref trait 和 Drop trait