傳遞參考給函式

YouTube 上觀看本章內容: 不可變參考可變參考

參考對函式非常有用。Rust 中關於值的規則是:一個值只能有一個所有者。

這段程式碼將無法運作:

fn print_country(country_name: String) {
    println!("{}", country_name);
}

fn main() {
    let country = String::from("Austria");
    print_country(country); // 我們印出 "Austria"
    print_country(country); // ⚠️ 蠻有趣的,讓我們再做一次!
}

它不能運作,因為 country 被銷毀了。它是這麼來的:

  • 第一步:我們建立稱為 countryStringcountry 是所有者。
  • 第二步:我們把 country 給了 print_countryprint_country 沒有 ->,所以它不回傳任何東西。在 print_country 完成後,我們的 String 現在已經死了。
  • 第三步:我們嘗試把 countryprint_country,但我們已經這樣做過了。我們已經沒有 country 可以給了。

我們可以讓 print_country 給回 String,但是有點奇怪。

fn print_country(country_name: String) -> String {
    println!("{}", country_name);
    country_name // 這裡回傳它
}

fn main() {
    let country = String::from("Austria");
    let country = print_country(country); // 我們現在要在這裡用 let 拿回 String
    print_country(country);
}

現在印出了:

Austria
Austria

更好的解決方式是加上 &

fn print_country(country_name: &String) {
    println!("{}", country_name);
}

fn main() {
    let country = String::from("Austria");
    print_country(&country); // 我們印出 "Austria"
    print_country(&country); // 蠻有趣的,讓我們再做一次!
}

現在 print_country() 是一個函式,接受 String 的參考:即 &String。另外,我們寫 &country 來給 country 一個參考,。這表示 "你可以查看它,但我會保有它"。

現在讓我們用一個可變參考來做類似的事情。這是個使用可變變數的函式範例:

fn add_hungary(country_name: &mut String) { // 首先我們說函式接受一個可變參考
    country_name.push_str("-Hungary"); // push_str() 加入 &str 到 String
    println!("Now it says: {}", country_name);
}

fn main() {
    let mut country = String::from("Austria");
    add_hungary(&mut country); // 我們也要給它可變參考。
}

這印出了 Now it says: Austria-Hungary

所以得出結論:

  • fn function_name(variable: String) 接受 String 並擁有它。如果它不回傳任何東西,那麼這個變數就會死在函數裡面。
  • fn function_name(variable: &String) 借用 String 並可以查看它
  • fn function_name(variable: &mut String) 借用 String 並可以更改

這是個看起來像可變參考但不同的範例。

fn main() {
    let country = String::from("Austria"); // country 是不可變的,但我們想要印出 Austria-Hungary。怎麼做?
    adds_hungary(country);
}

fn adds_hungary(mut country: String) { // 它是這樣做的:adds_hungary 接受 String 並宣告它是可變的!
    country.push_str("-Hungary");
    println!("{}", country);
}

這怎麼可能呢?因為 mut country 不是參考。adds_hungary 現在擁有 country。(記得,它接受的是 String 而不是 &String)。當你呼叫 adds_hungary 的那一刻,它就完全成了 country 的所有者。countryString::from("Austria") 沒有關係了。所以,adds_hungary 可以把 country 當作可變的,這樣做是完全安全的。

還記得前面我們的員工 Powerpoint 和經理的情況嗎?在這種情況下,就好比員工只是把自己的整臺電腦交給了經理。員工不會再碰它,所以經理可以對它做任何他想做的事情。