name: m02-resource description: “关键:用于智能指针和资源管理。触发词:Box、Rc、Arc、Weak、RefCell、Cell、智能指针、堆分配、引用计数、RAII、Drop、应该用Box还是Rc、何时用Arc vs Rc、智能指针、引用计数、堆分配” user-invocable: false
资源管理
第1层:语言机制
核心问题
这个资源需要什么样的所有权模式?
在选择智能指针之前,先理解:
- 所有权是单一的还是共享的?
- 访问是单线程的还是多线程的?
- 是否存在潜在的循环引用?
错误 → 设计问题
| 错误 | 不要只是说 | 而是应该问 |
|---|---|---|
| “需要堆分配” | “用Box” | 为什么不能放在栈上? |
| Rc内存泄漏 | “用Weak” | 循环引用在设计中是必要的吗? |
| RefCell panic | “用try_borrow” | 运行时检查是正确的方法吗? |
| 抱怨Arc开销 | “接受它” | 真的需要多线程访问吗? |
思考提示
在选择智能指针之前:
-
所有权模型是什么?
- 单一所有者 → Box 或 拥有所有权的值
- 共享所有权 → Rc/Arc
- 弱引用 → Weak
-
线程上下文是什么?
- 单线程 → Rc, Cell, RefCell
- 多线程 → Arc, Mutex, RwLock
-
存在循环引用吗?
- 是 → 其中一个方向必须是 Weak
- 否 → 常规的 Rc/Arc 即可
向上追溯 ↑
当指针选择不明确时,追溯到设计:
"我应该用 Arc 还是 Rc?"
↑ 问:这个数据是否跨线程共享?
↑ 检查:m07-concurrency (线程模型)
↑ 检查:domain-* (性能约束)
| 情况 | 追溯到 | 问题 |
|---|---|---|
| Rc vs Arc 困惑 | m07-concurrency | 并发模型是什么? |
| RefCell panic | m03-mutability | 内部可变性在这里合适吗? |
| 内存泄漏 | m12-lifecycle | 清理应该在哪里发生? |
向下推导 ↓
从设计到实现:
"需要单一所有者的堆数据"
↓ 使用:Box<T>
"需要共享不可变数据 (单线程)"
↓ 使用:Rc<T>
"需要共享不可变数据 (多线程)"
↓ 使用:Arc<T>
"需要打破引用循环"
↓ 使用:Weak<T>
"需要共享可变数据"
↓ 单线程:Rc<RefCell<T>>
↓ 多线程:Arc<Mutex<T>> 或 Arc<RwLock<T>>
快速参考
| 类型 | 所有权 | 线程安全 | 使用场景 |
|---|---|---|---|
Box<T> |
单一 | 是 | 堆分配,递归类型 |
Rc<T> |
共享 | 否 | 单线程共享所有权 |
Arc<T> |
共享 | 是 | 多线程共享所有权 |
Weak<T> |
弱引用 | 与 Rc/Arc 相同 | 打破引用循环 |
Cell<T> |
单一 | 否 | 内部可变性 (Copy 类型) |
RefCell<T> |
单一 | 否 | 内部可变性 (运行时检查) |
决策流程图
需要堆分配吗?
├─ 是 → 单一所有者?
│ ├─ 是 → Box<T>
│ └─ 否 → 多线程?
│ ├─ 是 → Arc<T>
│ └─ 否 → Rc<T>
└─ 否 → 栈分配 (默认)
存在引用循环吗?
├─ 是 → 一个方向使用 Weak
└─ 否 → 常规 Rc/Arc
需要内部可变性吗?
├─ 是 → 需要线程安全吗?
│ ├─ 是 → Mutex<T> 或 RwLock<T>
│ └─ 否 → T: Copy? → Cell<T> : RefCell<T>
└─ 否 → 使用 &mut T
常见错误
| 问题 | 原因 | 修复方法 |
|---|---|---|
| Rc 循环泄漏 | 相互强引用 | 一个方向使用 Weak |
| RefCell panic | 运行时借用冲突 | 使用 try_borrow 或重构代码 |
| Arc 开销 | 热点路径中的原子操作 | 如果是单线程,考虑使用 Rc |
| 不必要的 Box | 数据适合栈 | 移除 Box |
反模式
| 反模式 | 为什么不好 | 更好的做法 |
|---|---|---|
| 到处用 Arc | 不必要的原子操作开销 | 单线程时使用 Rc |
| 到处用 RefCell | 运行时 panic | 设计清晰的所有权 |
| 对小类型用 Box | 不必要的分配 | 栈分配 |
| 忽略 Weak 处理循环 | 内存泄漏 | 设计父子关系时使用 Weak |
相关技能
| 何时 | 查看 |
|---|---|
| 所有权错误 | m01-ownership |
| 内部可变性详情 | m03-mutability |
| 多线程上下文 | m07-concurrency |
| 资源生命周期 | m12-lifecycle |