第五节、引用和借用
引用和借用
先介绍一下References (引用)和 Borrowing(借用)的概念
引用类似C语言的指针,使用&符号。不同的是指针是可以完全使用和修改内容的。引用只能获取信息,不具有所有权,不能修改。
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
上面的代码是获取 s1的长度,这个是可以的。
fn main() {
let s = String::from("hello");
change(&s);
}
fn change(some_string: &String) {
some_string.push_str(", world");
}
例子2是会报错的
我们看一下 s和s1的 引用图,
可变的引用
我们通过一些小的调整来修改借用( borrowed)的值,而这些小调整就能可变引用(reference):
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
首先,我们更改s为mut。&mut s然后我们在调用函数的地方创建一个可变引用change,并更新函数签名以接受一个可变引用some_string: &mut String。这清楚地表明该change函数将改变它借用的值。
可变引用有一个很大的限制:一次只能有一个对特定数据的可变引用。尝试创建两个可变引用的代码s将失败:
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
如果使用2个变量来访问可变引用,需要加一个{}来做作用域隔离。
let mut s = String::from("hello");
{
let r1 = &mut s;
} // r1 goes out of scope here, so we can make a new reference with no problems.
let r2 = &mut s;
可变引用和 不可变引用 是不能同时存在的
let mut s = String::from("hello");
let r1 = &s; // no problem
let r2 = &s; // no problem
let r3 = &mut s; // BIG PROBLEM
println!("{}, {}, and {}", r1, r2, r3);
下面的代码是可以的。
let mut s = String::from("hello");
let r1 = &s; // no problem
let r2 = &s; // no problem
println!("{} and {}", r1, r2);
// variables r1 and r2 will not be used after this point
这之后r1,r2不再使用了。
let r3 = &mut s; // no problem
println!("{}", r3);
悬空引用
fn main() {
let reference_to_nothing = dangle();
}
fn dangle() -> &String {
let s = String::from("hello");
&s
}
s的作用域在dangle函数范围内,当dangle结束了,s会被释放。 这时候引用会被出错。
只能把s返回,延续s的所有权
fn no_dangle() -> String {
let s = String::from("hello");
s
}