函数的引用
引用对函数非常有用。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
,称为country
。country
是所有者。 - 第二步:我们把
country
给print_country
。print_country
没有->
,所以它不返回任何东西。print_country
完成后,我们的String
现在已经死了。 - 第三步:我们尝试把
country
给print_country
,但我们已经这样做了。我们已经没有country
可以给了。
我们可以让print_country
给String
回来,但是有点尴尬。
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的主人。country
与String::from("Austria")
没有关系了。所以,adds_hungary
可以把country
当作可变的,这样做是完全安全的。
还记得我们上面的员工Powerpoint和经理的情况吗?在这种情况下,就好比员工只是把自己的整台电脑交给了经理。员工不会再碰它,所以经理可以对它做任何他想做的事情。