iT邦幫忙

0

二、三天學一點點 Rust:來! 擁有權Ownership之三(19)

  • 分享至 

  • xImage
  •  

🔄 Move 與 Ownership 擁有權的關係

在 Rust 中,每個值都有一個變數,該變數稱為該值的「擁有者」。擁有者的作用是,當擁有者離開作用域時,負責釋放該值所佔用的記憶體. 這確保了記憶體的安全釋放,防止了懸 dangling 指標和記憶體洩漏等問題。

fn main() {
    let person = String::from("Roger");
    let genious = person;
    println!("{}", genious);
}

📦 程式說明:

  1. String::from("Roger") 建立了一個堆積資料型別 String,並由變數 person 擁有其所有權。
  2. let genious = person; 表示將 person 的值賦給 genious,這在 Rust 中不是複製(copy),而是所有權轉移(move)
  3. 接著使用 genious 是合法的,因為它現在擁有該 String 的所有權。
  4. 若後續還使用 person,則會造成編譯錯誤,因為它已經不再擁有該資料。

🔍 Move 與 Ownership 關係對照表

概念 說明
所有權(Owner) 每筆堆積資料只能有一個擁有者
Move 行為 將所有權從一個變數移轉到另一個變數,原變數失效
Copy vs Move Copy 型別(如整數)會複製資料;非 Copy 型別(如 String)則會 Move
編譯器檢查 編譯器會在編譯時阻止對已失去所有權的變數使用,防止重複釋放記憶體

❌ 若錯誤地使用已被 Move 的變數

假如你在 println!() 中這樣寫:

println!("{}", person);

將會導致編譯錯誤,還會貼心提醒擁有權已經移動轉到genious:

error[E0382]: borrow of moved value: `person`                                                             
  --> src\main.rs:15:20
   |
13 |     let person = String::from("Roger");
   |         ------ move occurs because `person` has type `String`, which does not implement the `Copy` trait
14 |     let genious = person;
   |                   ------ value moved here
15 |     println!("{}", person);
   |                    ^^^^^^ value borrowed here after move

這是 Rust 在保護你的記憶體安全,防止「雙重釋放」(Double Free)等錯誤。


✅ 小結:何時會發生 Move?

型別 是否會發生 Move? 說明
i32bool ❌ 不會(它們是 Copy 型別) 複製資料即可
String ✅ 會發生 Move 移轉所有權以避免記憶體重複釋放
Vec<T> ✅ 會發生 Move 同樣屬於堆積資料,遵守所有權系統

🗑️ drop() 函數與擁有權(Ownership)

在 Rust 中,每個值都有一個擁有者。當擁有者離開作用域時,Rust 會自動呼叫該值的 drop 函式(如果該型別實作了 Drop trait)。對於像 String 這種擁有堆積分配記憶體的型別,drop 函式的預設行為是釋放該記憶體,防止記憶體洩漏.

fn main() {
    let person = String::from("Roger");

    drop(person);              // 明確手動釋放 person 的資源
    let genious = person;      // ❌ 錯誤:person 已經被 drop,無法再使用
}

✅ Rust 中的 drop() 函數是什麼?

  • drop() 是 Rust 標準函式庫中提供的函數,用來提早釋放資源(記憶體)
  • 當你呼叫 drop(person) 時,等同於變數 person 離開作用域時自動被清理
  • 使用後,該變數的所有權就「結束」,你就不能再使用它。

📚 參考文件:std::mem::drop - Rust Docs


🧠 擁有權與記憶體釋放的關係

Rust 會在變數離開作用域時自動呼叫 drop(),這是 Rust 的記憶體安全保證機制。

fn main() {
    let name = String::from("Alice");    
}// 當 main 結束,name 會自動被 drop

你也可以用 drop() 手動提前釋放資源,不必等作用域結束。


🔍 drop() 的行為總結

行為類型 說明
自動 drop 變數離開作用域時自動呼叫,釋放資源
手動 drop 使用 drop(var) 明確釋放資源,立即失去所有權
drop 後狀態 該變數無法再被使用,會造成編譯錯誤
與 Copy 的關係 Copy 型別不需要 drop,無資源釋放需求
與 Move 的關係 Move 後的變數會失效,新的變數負責 drop

❌ 錯誤示範解說

在以下程式中:

let person = String::from("Roger");
drop(person);
let genious = person; // ❌ 錯誤!person 的所有權已被釋放

這段會報錯:

error[E0382]: use of moved value: `person`

因為 drop(person) 奪走了所有權並釋放記憶體,接下來的 person 就失效了。


✅ 小結:drop() 與所有權的關鍵關係

比較項目 說明
drop() 時機 可以是自動(離開作用域)或手動(調用 drop)
呼叫後會怎樣? 變數失效,不能再被使用
用途 提前釋放大量資源或控制釋放順序
所有權系統的角色 確保每個資源有且只有一個負責釋放的所有者

Rust 的自動 drop 行為簡化了記憶體管理,防止了記憶體洩漏。drop 函式允許我們自訂資源釋放的行為,而顯式呼叫 drop 則提供了提前釋放資源的靈活性。理解 drop 函式和所有權的關係對於編寫高效且安全的 Rust 程式至關重要。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言