智能指针

指针 是一个通用概念,指的是一个包含内存地址的变量。这个地址指向或“引用”其他数据。在 Rust 中,最常见的指针类型是引用,你在第 4 章中已经学习过。引用由 & 符号表示,并借用它们所指向的值。除了引用数据外,它们没有任何特殊功能,也没有额外的开销。

智能指针 则是一种数据结构,它们不仅像指针一样工作,还拥有额外的元数据和功能。智能指针的概念并不是 Rust 独有的:智能指针起源于 C++,并且也存在于其他语言中。Rust 标准库中定义了多种智能指针,它们提供了引用所不具备的功能。为了探索这一通用概念,我们将看几个不同的智能指针示例,包括一个_引用计数_智能指针类型。这种指针通过跟踪所有者的数量,使得数据可以有多个所有者,并在没有所有者时清理数据。

Rust 的所有权和借用概念使得引用和智能指针之间有一个额外的区别:引用只是借用数据,而在许多情况下,智能指针_拥有_它们所指向的数据。

尽管我们在之前没有这样称呼它们,但我们在本书中已经遇到过一些智能指针,包括第 8 章中的 StringVec<T>。这两种类型都被视为智能指针,因为它们拥有一些内存并允许你对其进行操作。它们还具有元数据和额外的功能或保证。例如,String 将其容量存储为元数据,并具有确保其数据始终是有效 UTF-8 的额外能力。

智能指针通常使用结构体来实现。与普通结构体不同,智能指针实现了 DerefDrop trait。Deref trait 允许智能指针结构体的实例像引用一样行为,因此你可以编写代码来处理引用或智能指针。Drop trait 允许你自定义智能指针实例超出作用域时运行的代码。在本章中,我们将讨论这两个 trait,并展示它们对智能指针的重要性。

鉴于智能指针模式是 Rust 中常用的通用设计模式,本章不会涵盖所有现有的智能指针。许多库都有自己的智能指针,你甚至可以编写自己的智能指针。我们将介绍标准库中最常见的智能指针:

  • Box<T>,用于在堆上分配值
  • Rc<T>,一种引用计数类型,允许多重所有权
  • Ref<T>RefMut<T>,通过 RefCell<T> 访问,这是一种在运行时而不是编译时强制执行借用规则的类型

此外,我们将介绍_内部可变性_模式,即不可变类型暴露一个用于改变内部值的 API。我们还将讨论_引用循环_:它们如何导致内存泄漏以及如何防止它们。

让我们开始吧!