Rust 中的指针和智能指针
type
status
date
slug
summary
tags
category
icon
password
A pointer is a general concept for a variable that contains an address in memory. This address refers to, or “points at,” some other data. The most common kind of pointer in Rust is a reference, which you learned about in Chapter 4. References are indicated by the&
symbol and borrow the value they point to. They don’t have any special capabilities other than referring to data, and have no overhead.Smart pointers, on the other hand, are data structures that act like a pointer but also have additional metadata and capabilities. The concept of smart pointers isn’t unique to Rust: smart pointers originated in C++ and exist in other languages as well. Rust has a variety of smart pointers defined in the standard library that provide functionality beyond that provided by references. To explore the general concept, we’ll look at a couple of different examples of smart pointers, including a reference counting smart pointer type. This pointer enables you to allow data to have multiple owners by keeping track of the number of owners and, when no owners remain, cleaning up the data.
指针 (pointer)是一个包含内存地址的变量的通用概念。这个地址引用 或 “指向”(points at)一些其他数据。Rust 中最常见的指针是第四章介绍的引用(reference)。引用以
&
符号为标志并借用了他们所指向的值。除了引用数据没有任何其他特殊功能,也没有额外开销。另一方面,智能指针(smart pointers)是一类数据结构,他们的表现类似指针,但是也拥有额外的元数据和功能。智能指针的概念并不为 Rust 所独有;其起源于 C++ 并存在于其他语言中。Rust 标准库中定义了多种不同的智能指针,它们提供了多于引用的额外功能。为了探索其基本概念,我们来看看一些智能指针的例子,这包括引用计数 (reference counting)智能指针类型。这种指针允许数据有多个所有者,它会记录所有者的数量,当没有所有者时清理数据。在 Rust 中因为引用和借用,普通引用和智能指针的一个额外的区别是引用是一类只借用数据的指针;相反,在大部分情况下,智能指针拥有他们指向的数据。
普通指针
普通的指针(Pointer),也就是引用(Reference),是对数据的借用(Borrow),无论是可变引用还是不可变引用,都不会拥有数据
在任何时候,要么只能有一个可变引用,要么只能有多个不可变引用
智能指针
Box<T>
智能指针则会拥有值的所有权:
Rc<T>
通过 Box 可以访问和修改堆上的数据, 但 Box 的缺点在于: 同一时间只能有一个指针是有效的, Box 无法被克隆, 只能将所有权转移给另一个智能指针。而另一种智能指针 Rc 则可以进行克隆,这相当于可以让一个值同时被多处拥有,但 Rc 的引用都是不可变引用,即不能用来修改原始数据:
如果想让 Rc 也能修改原始的数据, 可以用 RefCell 进行配合
RefCell<T>
严格来讲,RefCell 不是一种指针,而是一种提供内部可变性的容器。在上面的几个例子中,结构体变量 x 均使用了 mut 进行修饰,因为需要尝试对 x 的内部字段进行修改。但假如有这样一种需求:只能修改 Person 的 age 字段,而不能修改 name 字段。如果去掉修饰 x 的 mut,则 x 的所有字段都无法修改,加上 mut,x 的所有字段又都能修改,都不能满足需求。RefCell 提供的内部可变性则可以应对这种情况:
因此,RefCell 可以让本来不能被修改的 T 变得可以修改。这一特性让 RefCell 非常适合与 Rc 一起使用,即 Rc<Ref<T>>。前面已经说过, Rc<T> 可以使数据被多次引用,但每个引用都是不可变引用。RefCell<T> 则忽略引用是否可变,强行对其进行修改,两者配合,就能实现一个数据拥有多个可变引用
Cow<T>
Cow
的是 Clone On Write 的缩写,他可以在需要写的时候才对包裹的对象进行克隆