iT邦幫忙

0

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

  • 分享至 

  • xImage
  •  

🦀 函式參數與擁有權(Function Parameters and Ownership)

Rust 的所有權機制不只在變數之間賦值時會生效,傳遞參數給函式時也會觸發「所有權轉移(ownership move)」或「複製(copy)」。此外,函式的回傳值也會牽涉所有權的轉移。以下透過四個例子分別說明:Copy 型別、非 Copy 型別、使用 mut 修改參數,以及回傳值的擁有權轉移。


✅ 範例一:Copy 型別(如 i32

fn main()  {
    let x = 5;
    makes_copy(x);
    println!("{}", x); // ✅ 可以繼續使用 x,因為 i32 是 Copy 型別
}

fn makes_copy(some_integer: i32) {
    println!("{}", some_integer);
}

🔍 說明:

  • xi32,屬於 Copy 型別。
  • 呼叫 makes_copy(x) 時,傳遞的是複製值,不是移轉所有權。
  • 因此 x 在函式呼叫後仍然可以使用。

📘 Copy 型別特性整理

型別 是否 Copy 傳入函式時會怎樣
i32 ✅ 是 複製一份值
bool ✅ 是 複製一份值
char ✅ 是 複製一份值
f64 ✅ 是 複製一份值

❌ 範例二:非 Copy 型別(如 String

fn main() {
    let oranges = String::from("Oranges");
    print_my_value(oranges);
    println!("{}", oranges); // ❌ 錯誤:所有權已移轉給函式
}

fn print_my_value(value: String) {
    println!("{}", value);
}

🔍 說明:

  • String 是堆積型別,不實作 Copy trait
  • 當傳入函式 print_my_value(oranges),會觸發 所有權轉移(move)
  • 在函式內部 value 成為新擁有者。
  • main() 裡的 oranges 在那之後不能再使用,否則會編譯錯誤。

📘 非 Copy 型別行為整理

型別 是否 Copy 傳入函式時會怎樣
String ❌ 否 移轉所有權
Vec<T> ❌ 否 移轉所有權
Box<T> ❌ 否 移轉所有權

🔧 範例三:使用 mut 修改函式內部參數

fn main() {
    let burger = String::from("Burger");
    add_fries(burger); // 所有權移轉到函式中
}

fn add_fries(mut meal: String) {
    meal.push_str(" and Fires");
    println!("{}", meal);
}

🔍 說明:

  • burgerString,非 Copy 型別,傳入函式時發生 所有權轉移
  • mut meal 表示在函式內部,這個參數是可變的,可修改字串內容。
  • 雖然參數可變,但仍然不是原本變數可變,而是所有權已轉移後的新變數。
  • 函式結束後 meal 被 drop,burger 也因此失效,無法再使用。

📘 可變參數與所有權關係

特性項目 說明
mut 參數 表示函式內部的參數可以改變(僅限內部使用)
所有權轉移 呼叫時會發生 move,原變數將無法再使用
修改後不回傳值 若希望修改完還能使用原變數,需搭配 &mut 參照方式處理

🔁 範例四:回傳值會移轉所有權

fn main() {
    let cake = bake_cake(); 
    println!("I now have a {} cake.", cake); 
}

fn bake_cake() -> String { 
    let cake_name = String::from("Chocolate Mousse"); 
    cake_name // 可簡寫為:String::from("Chocolate Mousse")
}

🔍 說明:

  • 函式 bake_cake() 內部建立一個 String
  • 回傳這個變數會導致其所有權被移轉到呼叫者(main 的 cake)
  • 因此 cake 變數現在擁有回傳的字串,可以安全使用。
  • 這也是 Rust 在沒有垃圾回收下,安全移動資料的方式之一。

📘 回傳值與所有權關係

行為項目 說明
回傳 Copy 型別 值被複製(如 i32)
回傳非 Copy 型別 所有權被移轉(如 String、Vec)
可簡寫函式 如果回傳的是表達式,最後一行可省略 return 與分號

✅ 小結

類型分類 是否移轉所有權 可否修改 備註
Copy 型別 ❌ 否(會複製) ✅ 可以修改副本 呼叫函式後變數仍可使用
非 Copy 型別 ✅ 是 ✅ 可變(需 mut 呼叫函式後變數失效,除非用借用或 clone
回傳值 ✅ 是(非 Copy) ✅ 可用 回傳即表示所有權移交

Rust 強迫我們思考變數的擁有權,在函式參數與回傳值中尤其重要。若希望保留變數又要傳入函式,可以改用 &value 借用參照,或使用 .clone() 複製堆積資料。


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

尚未有邦友留言

立即登入留言