函数的引用

引用对函数非常有用。Rust中关于值的规则是:一个值只能有一个所有者。

这段代码将无法工作:

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

fn main() {
    let country = String::from("Austria");
    print_country(country); // We print "Austria"
    print_country(country); // ⚠️ That was fun, let's do it again!
}

它不能工作,因为country被破坏了。下面是如何操作的。

  • 第一步,我们创建String,称为countrycountry是所有者。
  • 第二步:我们把countryprint_countryprint_country没有->,所以它不返回任何东西。print_country完成后,我们的String现在已经死了。
  • 第三步:我们尝试把countryprint_country,但我们已经这样做了。我们已经没有country可以给了。

我们可以让print_countryString回来,但是有点尴尬。

fn print_country(country_name: String) -> String {
    println!("{}", country_name);
    country_name // return it here
}

fn main() {
    let country = String::from("Austria");
    let country = print_country(country); // we have to use let here now to get the String back
    print_country(country);
}

现在打印出来了。

Austria
Austria

更好的解决方法是增加&

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

fn main() {
    let country = String::from("Austria");
    print_country(&country); // We print "Austria"
    print_country(&country); // That was fun, let's do it again!
}

现在 print_country() 是一个函数,它接受 String 的引用: &String。另外,我们给country一个引用,写作&country。这表示 "你可以看它,但我要保留它"。

现在让我们用一个可变引用来做类似的事情。下面是一个使用可变变量的函数的例子:

fn add_hungary(country_name: &mut String) { // first we say that the function takes a mutable reference
    country_name.push_str("-Hungary"); // push_str() adds a &str to a String
    println!("Now it says: {}", country_name);
}

fn main() {
    let mut country = String::from("Austria");
    add_hungary(&mut country); // we also need to give it a mutable reference.
}

此打印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 is not mutable, but we are going to print Austria-Hungary. How?
    adds_hungary(country);
}

fn adds_hungary(mut country: String) { // Here's how: adds_hungary takes the String and declares it mutable!
    country.push_str("-Hungary");
    println!("{}", country);
}

这怎么可能呢?因为mut country不是引用。adds_hungary现在拥有country。(记住,它占用的是String而不是&String)。当你调用adds_hungary的那一刻,它就完全成了country的主人。countryString::from("Austria")没有关系了。所以,adds_hungary可以把country当作可变的,这样做是完全安全的。

还记得我们上面的员工Powerpoint和经理的情况吗?在这种情况下,就好比员工只是把自己的整台电脑交给了经理。员工不会再碰它,所以经理可以对它做任何他想做的事情。