智能指针
Rust 中的智能指针是一种数据结构,它不仅表现得像一个指针(通过实现 Deref
trait),还拥有额外的元数据和功能(最典型的是所有权和生命周期管理)。它们通常使用结构体实现,并实现了 Deref
和 Drop
这两个关键的 trait。
Deref
: 通过实现 Deref,你可以使用 *
解引用运算符来访问其内部的数据和使用 &
来取得内部数据的引用。Drop
: 允许你在值离开作用域时执行自定义的清理代码
Deref
For example: &
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
}
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
fn hello(name: &str) {
println!("Hello, {}!", name);
}
fn main() {
let m = MyBox::new(String::from("Rust"));
// 这里发生了 Deref Coercion!
hello(&m);
// 如果没有 Deref Coercion,你需要这样写:
hello(&(*m)[..]);
// 或者这样:
hello(m.deref());
}
|
转换过程分析
当编译器看到 hello(&m)
时:
m
的类型是 MyBox<String>
&m
的类型是 &MyBox<String>
- 但
hello
函数需要 &str
- 编译器发现
MyBox<T>
实现了 Deref<Target = T>
- 于是开始一系列自动转换:
&MyBox<String>
→ &String
(因为 MyBox<T>
的 Target
是 T
)&String
→ &str
(因为 String
也实现了 Deref<Target = str>
)
For example: *
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
}
// 关键:实现 Deref trait
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0 // 返回内部数据的引用
}
}
fn main() {
let x = 5;
let y = MyBox::new(x);
// 现在可以工作了!
println!("{}", *y); // 输出: 5
// 这相当于:
println!("{}", *(y.deref())); // 显式调用 deref 方法
}
|
Drop
For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| struct CustomSmartPointer {
data: String,
}
impl Drop for CustomSmartPointer {
fn drop(&mut self) {
println!("Dropping CustomSmartPointer with data `{}`!", self.data);
}
}
fn main() {
let c = CustomSmartPointer { data: String::from("my stuff") };
let d = CustomSmartPointer { data: String::from("other stuff") };
println!("CustomSmartPointers created.");
// 这里会自动调用 c.drop() 和 d.drop()
}
// 输出:
// CustomSmartPointers created.
// Dropping CustomSmartPointer with data `other stuff`!
// Dropping CustomSmartPointer with data `my stuff`!
|
Rust 标准库常见的智能指针
Rust 标准库中最常见的智能指针包括:
Box<T>
: 在堆上分配数据;处理递归类型;trait 对象 (单一所有权)Rc<T>
: 单线程下的多重只读所有权 (共享所有权)Arc<T>
: 多线程下的多重只读所有权 (共享所有权)RefCell<T>
: 单线程下的内部可变性 (单一所有权)Mutex<T>
和 RwLock<T>
: 多线程下的内部可变性和互斥访问 (单一所有权)
常见组合:
Rc<RefCell<T>>
:单线程下的共享可变数据。Arc<Mutex<T>>
或 Arc<RwLock<T>>
:多线程下的共享可变数据。
对于所有权来说, Rc 和 Arc 对应 C++ 的 shared_ptr, 其他对应 unique_ptr。