所有權與記憶體模型
深入學習 Rust 的所有權系統、借用規則和記憶體管理,理解與 JavaScript 垃圾回收的差異
所有權與記憶體模型
📖 學習目標
理解 Rust 的所有權系統,這是 Rust 最核心的概念。我們將從 JavaScript 的記憶體管理出發,逐步理解 Rust 如何透過編譯時檢查確保記憶體安全。
🎯 記憶體管理對比
JavaScript 的垃圾回收
JavaScript 使用自動垃圾回收機制:
正在加载...
Rust 的所有權系統
Rust 使用所有權系統在編譯時管理記憶體:
正在加载...
記憶體管理差異
- 自動 vs 手動: JavaScript 自動垃圾回收,Rust 編譯時檢查
- 引用語義: JavaScript 物件透過引用傳遞,Rust 透過所有權轉移
- 記憶體安全: JavaScript 執行時檢查,Rust 編譯時保證
- 效能: JavaScript 有垃圾回收開銷,Rust 零成本抽象
🔄 所有權規則
Rust 的所有權規則
Rust 有三個核心所有權規則:
正在加载...
🔗 借用與引用
不可變借用
正在加载...
可變借用
正在加载...
借用規則
正在加载...
📏 生命週期
生命週期註解
正在加载...
🎯 所有權與 JavaScript 對比
資料傳遞對比
正在加载...
🎯 練習題
練習 1: 所有權轉移
分析以下程式碼,指出哪些地方會發生所有權轉移:
fn main() {let s1 = String::from("hello");let s2 = s1;let s3 = s2.clone();println!("s2: {}", s2);println!("s3: {}", s3);}
查看答案
let s2 = s1;
- s1 的所有權移動到 s2let s3 = s2.clone();
- s2 被複製,s3 獲得新資料的所有權- s2 仍然有效,因為 clone 建立了新的資料
練習 2: 借用規則
修復以下程式碼中的借用錯誤:
fn main() {let mut data = vec![1, 2, 3];let ref1 = &data;let ref2 = &mut data;println!("{:?}, {:?}", ref1, ref2);}
查看答案
fn main() {let mut data = vec![1, 2, 3];let ref1 = &data;let ref2 = &data; // 改為不可變引用println!("{:?}, {:?}", ref1, ref2);// 或者先使用不可變引用,再使用可變引用let mut data = vec![1, 2, 3];let ref1 = &data;println!("{:?}", ref1);let ref2 = &mut data; // 現在可以使用可變引用ref2.push(4);println!("{:?}", ref2);}
練習 3: 生命週期
為以下函數添加正確的生命週期註解:
fn longest(x: &str, y: &str) -> &str {if x.len() > y.len() {x} else {y}}
查看答案
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {if x.len() > y.len() {x} else {y}}
📝 總結
在這一章中,我們深入學習了 Rust 的所有權系統:
- 所有權規則: 每個值只有一個所有者,所有者離開作用域時值被丟棄
- 借用系統: 透過引用借用資料,避免所有權轉移
- 借用規則: 同一時間只能有一個可變引用或多個不可變引用
- 生命週期: 確保引用在有效期內使用
- 與 JavaScript 對比: Rust 編譯時檢查 vs JavaScript 執行時垃圾回收
關鍵要點
- 所有權系統是 Rust 記憶體安全的核心
- 借用系統允許在不轉移所有權的情況下使用資料
- 生命週期系統確保引用始終有效
- 這些概念在編譯時檢查,執行時零開銷
常見陷阱
- 移動後使用: 值被移動後不能再使用
- 同時借用: 不能同時有可變和不可變借用
- 懸垂引用: 返回對局部變數的引用
- 生命週期不匹配: 引用生命週期不匹配
下一步學習
在下一章中,我們將學習 Rust 的並發和異步程式設計模型,了解如何安全地處理多執行緒和異步操作。
繼續學習: 並發與異步模型