智能指针
一个 指针 是一个通用的概念,表示一个包含内存地址的变量。这个地址指向或“指向”其他一些数据。Rust 中最常见的指针类型是引用,你在第 4 章中已经学过。引用由 &
符号表示,并借用它们指向的值。它们除了引用数据之外没有任何特殊功能,并且没有开销。
智能指针,另一方面,是像指针一样行为的数据结构,但还具有额外的元数据和功能。智能指针的概念并非 Rust 独有:智能指针起源于 C++,并且在其他语言中也存在。Rust 在标准库中定义了多种智能指针,提供了超出引用所提供的功能。为了探讨这一通用概念,我们将查看几种不同的智能指针示例,包括一个引用计数智能指针类型。这种指针通过跟踪所有者的数量,并在没有所有者时清理数据,使数据可以有多个所有者。
Rust 通过其所有权和借用的概念,在引用和智能指针之间引入了额外的区别:虽然引用只是借用数据,但在许多情况下,智能指针拥有它们指向的数据。
虽然我们在当时没有这样称呼它们,但在这本书中我们已经遇到了一些智能指针,包括第 8 章中的 String
和 Vec<T>
。这两种类型都算作智能指针,因为它们拥有某些内存并允许你操纵这些内存。它们还具有元数据和额外的功能或保证。String
例如,存储其容量作为元数据,并具有确保其数据始终为有效 UTF-8 的额外能力。
智能指针通常使用结构体实现。与普通结构体不同,智能指针实现了 Deref
和 Drop
特性。Deref
特性允许智能指针结构体的实例像引用一样行为,因此你可以编写可以与引用或智能指针一起工作的代码。Drop
特性允许你自定义智能指针实例超出作用域时运行的代码。在本章中,我们将讨论这两个特性,并演示它们对智能指针的重要性。
鉴于智能指针模式是 Rust 中常用的一种通用设计模式,本章不会涵盖所有现有的智能指针。许多库都有自己的智能指针,你甚至可以编写自己的。我们将介绍标准库中最常见的智能指针:
Box<T>
用于在堆上分配值Rc<T>
,一个引用计数类型,允许多个所有权。Ref<T>
和RefMut<T>
,通过RefCell<T>
访问,这是一种在运行时而不是编译时强制执行借用规则的类型。
此外,我们将介绍 内部可变性 模式,即一个不可变类型暴露出一个用于修改内部值的 API。我们还将讨论 引用循环:它们如何导致内存泄漏以及如何防止它们。
让我们开始吧!