智能指针
智能指针(smart pointer) 是实现了 Deref/Drop 等 trait 的复合类型,在「指针」之上附加了所有权、计数或借用检查等语义。
1. Box<T>:最简单的堆分配
fn main() {
let b = Box::new(5); // 把值放到堆上
println!("{}", b); // 像普通值一样用(Deref)
}常见用途:递归类型、特大对象、trait 对象。
enum List {
Cons(i32, Box<List>), // 递归必须靠 Box 确定大小
Nil,
}ℹ️为什么递归类型需要 Box
编译器需知道类型大小。Box<List> 是指针(固定大小),打破无限递归,让 List 大小可知。
2. Rc<T>:引用计数共享
单所有权不够用时,Rc 允许多个地方共享同一份只读数据:
use std::rc::Rc;
fn main() {
let shared = Rc::new(String::from("hi"));
let a = Rc::clone(&shared); // 计数 +1,不是深拷贝
let b = Rc::clone(&shared);
println!("引用计数 = {}", Rc::strong_count(&shared));
// a、b、shared 都指向同一数据
}⚠️Rc 只能单线程
Rc 不是线程安全的(无 Sync)。多线程共享用 Arc。且 Rc 内部数据默认不可变——要可变需配合 RefCell。
3. RefCell<T>:运行时借用检查
普通借用检查在编译期;RefCell 把检查推迟到运行时,从而能在「看似不可变」的 API 里做可变操作:
use std::cell::RefCell;
fn main() {
let cell = RefCell::new(5);
*cell.borrow_mut() += 1; // 运行时可变借用
println!("{}", cell.borrow()); // 运行时不可变借用
}💡Rc + RefCell 组合很常见
Rc<RefCell<T>> = 多所有者 + 可内部可变。这是 Rust 中「共享可变状态」的常见模式,但违反借用规则会在运行时 panic。
4. 对比 Box / Rc / RefCell
| 类型 | 所有权 | 借用检查 | 可变? |
|---|---|---|---|
Box<T> | 单一 | 编译期 | 取决于 mut |
Rc<T> | 多共享(只读) | 编译期 | 否 |
RefCell<T> | 单一 | 运行时 | 内部可变 |
5. Deref 与 Drop
智能指针能「像值一样用」是因为 Deref(解引用自动穿透),离开作用域自动 drop 是因为 Drop。
🎯练习
用 Rc<RefCell<Vec<i32>>> 模拟共享可变列表:创建两个 Rc 克隆,从一个里 borrow_mut().push 添加元素,验证另一个也能看到变化。观察强引用计数。
小结
Box堆分配,解决递归类型与 trait 对象大小问题Rc引用计数实现单线程多所有权共享(只读)RefCell把借用检查移到运行时,支持内部可变性Rc<RefCell<T>>是共享可变状态常用组合- 下一章看线程与并发 →