📘 目录
- 内存结构基础:栈、堆、数据段
- Rust 的内存管理机制(对比 C/C++、Java)
- Drop:Rust 的自动清理机制
- Deref:为什么
*x
能访问结构体内部值 - Rc:多个变量“共享一个资源”怎么办?
- Weak:如何打破 Rc 的循环引用?
- borrow_mut 和 downgrade 是什么意思?
- 👁 Rc / Weak / Deref / Drop 关系图
- 总结 & 使用建议
1️⃣ 内存结构基础
Rust 程序运行时,内存大致分为:
区域 | 用途说明 | 生命周期 |
---|---|---|
栈 | 存储函数调用的局部变量 | 函数调用期间 |
堆 | 存储动态分配的大对象 | 显式释放或自动释放 |
数据段 | 静态变量、全局变量等 | 程序运行全过程 |
2️⃣ Rust 的内存管理机制
- Rust 不靠垃圾回收器
- 通过“所有权 + 借用”系统管理内存
- 编译时就能判断内存是否正确释放
fn main() {let s = String::from("hello");let t = s;// println!("{}", s); // ❌ 错误:s 的所有权已经被转移给 t
}
3️⃣ Drop:变量作用域结束自动释放
你可以实现 Drop
trait,在变量被释放时自动执行逻辑。
struct Connection;impl Drop for Connection {fn drop(&mut self) {println!("连接关闭!");}
}fn main() {let _conn = Connection;println!("连接中…");
}
// 输出:连接中… ➤ 连接关闭!
4️⃣ Deref:让结构体支持 *x
Rust 中 *x
默认是用于“解引用”指针或引用。如果你想让自己写的结构体也支持 *x
,就需要实现 Deref
。
use std::ops::Deref;struct MyBox<T>(T);impl<T> Deref for MyBox<T> {type Target = T;fn deref(&self) -> &Self::Target {&self.0 // 访问结构体里的第一个字段}
}
5️⃣ Rc:多个变量想“共同拥有”一个资源?
默认变量所有权不能共享:
let a = String::from("hi");
let b = a; // a 不再拥有字符串
如果你希望多个变量共享一个资源(比如多个节点共享同一根节点),可以用:
use std::rc::Rc;let a = Rc::new(String::from("hello"));
let b = Rc::clone(&a); // ✅ 不是深拷贝,只是计数 +1
let c = Rc::clone(&a);
6️⃣ Weak:如何解决 Rc 的循环引用?
🌀 什么是循环引用?
a → b → a // 永远互相指着,永远无法释放
✅ Weak 是什么?
Rc<T>
:是“强引用”,决定资源释放Weak<T>
:是“弱引用”,不会影响资源生命周期
7️⃣ borrow_mut 和 downgrade 是什么意思?
🔹 borrow_mut 是什么?
当你使用 RefCell<T>
来包裹一个值时,可以在运行时借用它的可变引用。
use std::cell::RefCell;let x = RefCell::new(5);
*x.borrow_mut() = 10; // ✅ 可变借用并修改
解释:
.borrow_mut()
:是RefCell
提供的方法- 它返回一个可变引用,类似于
&mut T
,但是在运行时检查是否有冲突
📌 注意:不能同时有可变和不可变借用,否则运行时会 panic。
🔹 downgrade 是什么?
Rc::downgrade(&rc)
是把一个 Rc<T>
强引用变成 Weak<T>
弱引用。
let strong = Rc::new(String::from("Rust"));
let weak = Rc::downgrade(&strong); // 不增加引用计数
可以用 weak.upgrade()
把 Weak
转回 Rc
,如果值还活着,就返回 Some(Rc)
,否则是 None
。
🧪 示例:父子节点用 Weak 打破循环引用
use std::rc::{Rc, Weak};
use std::cell::RefCell;struct Node {value: i32,parent: RefCell<Option<Weak<Node>>>, // 👈 防止循环引用children: RefCell<Vec<Rc<Node>>>,
}fn main() {let parent = Rc::new(Node {value: 1,parent: RefCell::new(None),children: RefCell::new(vec![]),});let child = Rc::new(Node {value: 2,parent: RefCell::new(Some(Rc::downgrade(&parent))), // 🔥 不增加计数children: RefCell::new(vec![]),});parent.children.borrow_mut().push(child.clone());// 程序结束时能正确释放所有节点
}
8️⃣ 👁 Rc / Weak / Deref / Drop 关系图
┌────────────┐│ Rc<T> │◄─────┐└────────────┘ │ Rc::clone()▲ ││ ││ Rc::downgrade│▼ │┌────────────┐ ││ Weak<T> │────┐ │└────────────┘ │ ││ │ ││ upgrade() ▼ ▼│ ┌─────────┐│ │ *x 解引用│(Deref)▼ └─────────┘drop()(当 Rc 引用数为 0 自动触发)
✅ 总结 & 建议
工具 | 功能说明 | 典型使用场景 |
---|---|---|
Rc<T> | 多个所有者,共享资源 | 单线程共享结构,如树结构 |
Weak<T> | 不增加计数,防止循环引用 | 父指向子用 Rc,子指向父用 Weak |
RefCell<T> | 运行时可变借用检查 | 单线程内部可变性 |
borrow_mut | 在 RefCell 中获取可变引用 | RefCell<i32>.borrow_mut() |
downgrade | 将 Rc 转为 Weak,不影响引用计数 | 避免结构间强依赖 |
Deref | 让自定义类型也能用 *x 访问内部值 | 智能指针封装 |
Drop | 离开作用域时自动释放资源 | 自动释放连接、缓存等 |
、