📘 目录
- 内存结构基础:栈、堆、数据段
- Rust 的内存管理机制(对比 C/C++、Java)
- Drop:Rust 的自动清理机制
- Deref:为什么
*x
能访问结构体内部值 - Rc:多个变量"共享一个资源"怎么办?
- Weak:如何打破 Rc 的循环引用?
- borrow_mut 和 downgrade 是什么意思?
- 👁 Rc / Weak / Deref / Drop 关系图
- 总结 & 使用建议
1️⃣ 内存结构基础
Rust 程序运行时,内存大致分为:
区域 | 用途说明 | 生命周期 |
---|---|---|
栈 | 存储函数调用的局部变量 | 函数调用期间 |
堆 | 存储动态分配的大对象 | 显式释放或自动释放 |
数据段 | 静态变量、全局变量等 | 程序运行全过程 |
2️⃣ Rust 的内存管理机制
- Rust 不靠垃圾回收器
- 通过"所有权 + 借用"系统管理内存
- 编译时就能判断内存是否正确释放
rust
fn main() {
let s = String::from("hello");
let t = s;
// println!("{}", s); // ❌ 错误:s 的所有权已经被转移给 t
}
3️⃣ Drop:变量作用域结束自动释放
你可以实现 Drop
trait,在变量被释放时自动执行逻辑。
rust
struct Connection;
impl Drop for Connection {
fn drop(&mut self) {
println!("连接关闭!");
}
}
fn main() {
let _conn = Connection;
println!("连接中...");
}
// 输出:连接中... ➤ 连接关闭!
4️⃣ Deref:让结构体支持 *x
Rust 中 *x
默认是用于"解引用"指针或引用。如果你想让自己写的结构体也支持 *x
,就需要实现 Deref
。
rust
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:多个变量想"共同拥有"一个资源?
默认变量所有权不能共享:
rust
let a = String::from("hi");
let b = a; // a 不再拥有字符串
如果你希望多个变量共享一个资源(比如多个节点共享同一根节点),可以用:
rust
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 的循环引用?
🌀 什么是循环引用?
rust
a → b → a // 永远互相指着,永远无法释放
✅ Weak 是什么?
Rc<T>
:是"强引用",决定资源释放Weak<T>
:是"弱引用",不会影响资源生命周期
7️⃣ borrow_mut 和 downgrade 是什么意思?
🔹 borrow_mut 是什么?
当你使用 RefCell<T>
来包裹一个值时,可以在运行时借用它的可变引用。
rust
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>
弱引用。
rust
let strong = Rc::new(String::from("Rust"));
let weak = Rc::downgrade(&strong); // 不增加引用计数
可以用 weak.upgrade()
把 Weak
转回 Rc
,如果值还活着,就返回 Some(Rc)
,否则是 None
。
🧪 示例:父子节点用 Weak 打破循环引用
rust
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 |
离开作用域时自动释放资源 | 自动释放连接、缓存等 |
、