引用
假如我们想把传入的参数(没实现copy的)在调用方继续使用,一个比较笨的方式是
fn main() {
let s1 = String::from("hello");
let (s2, len) = calculate_length(s1);
println!("The length of '{}' is {}.", s2, len);
}
fn calculate_length(s: String) -> (String, usize) {
let length = s.len(); // len() returns the length of a String
(s, length)
}
也就是再返回回来,其实更好的方式是使用References,通过这种方式函数不需要获得所有权,看下面的代码
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传给calculate_length加了个&符号,也就是s指向了s1,calculate_length没有或的所有权
创建引用其实也叫借用,就是borrowing,但是借用过来的需要加mut才能修改
fn main() {
let mut s = String::from("hello");
change(&mut s);
println!("{}",s)
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
另外要知道,同时只有有一个可变引用,像下面就是错的:
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
当可变引用和不可变引用混用时,有两种情况
第一种情况,在构建可变引用后,不可变的引用还使用,这种会报错,就像下面这样
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); // 因为r1 和 r2使用了
但是如果不可变引用不用了,就不会报错,就像下面这样:
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
let r3 = &mut s; // no problem
println!("{}", r3);
Dangling References
什么叫Dangling References,也就是指向的东西被回收了,可以看下面这段代码
fn main() {
let reference_to_nothing = dangle();
}
fn dangle() -> &String {
let s = String::from("hello");
&s // 指向s,但是s指向的内容方法结束后就没了.
}
为了解决这个问题,可以直接将string返回:
fn no_dangle() -> String {
let s = String::from("hello");
s
}