📘 目錄
- 內存結構基礎:棧、堆、數據段
- 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 | 離開作用域時自動釋放資源 | 自動釋放連接、緩存等 |
、