感觉过段时间再看就不一样了,经常更新预定。
借用
借用,理解为变量的所有权的转移,与之对应的还有消耗(consume)。
fn main() {
let a = "测试".to_string();
let b = a;
println!("b={}", b);
println!("a={}", a);
}
由于a
的变量所有权发生转移,所以最后的打印语句无法执行。
error[E0382]: borrow of moved value: `a`
--> lifetime.rs:5:22
|
2 | let a = "测试".to_string();
| - move occurs because `a` has type `String`, which does not implement the `Copy` trait
3 | let b = a;
| - value moved here
4 | println!("b={}", b);
5 | println!("a={}", a);
| ^ value borrowed here after move
如果使用引用则没有问题:
fn main() {
let a = "测试".to_string();
let b = &a;
println!("b={}", b);
println!("a={}", a);
}
/*
b=测试
a=测试
*/
同时只能持有多个不变引用或一个可变引用。
//这样不行
fn main() {
let mut a = "测试".to_string();
let b = &a;
let c = &a;
let d = &mut a;
d.push_str("_D");
println!("b={}, c={}", b, c);
println!("d={}", d);
println!("a={}", a);
}
//这样可以
fn main() {
let mut a = "测试".to_string();
let b = &a;
let c = &a;
println!("b={}, c={}", b, c);
let d = &mut a;
d.push_str("_D");
println!("d={}", d);
println!("a={}", a);
}
/*
b=测试,c=测试
d=测试_D
a=测试_D
*/
//这样也可以
fn main() {
let mut a = "测试".to_string();
let d = &mut a;
d.push_str("_D");
println!("d={}", d);
let b = &a;
let c = &a;
println!("b={}, c={}", b, c);
println!("a={}", a);
}
/*
d=测试_D
b=测试_D, c=测试_D
a=测试_D
*/
另:用被大括号括住的块结算生命周期。
//这样不行
fn main() {
let a;
{
let b = "B".to_string();
a = &b;
}
println!("a={}", a);
}
括号完毕后 b 的生命周期视为结束,被释放。a 的借用找不到原变量,失效。
生命周期
生命周期用于保证不空引用/借用。
生命周期声明不影响实际的生命周期,只是描述了不同参数间的生命周期关系。
生命周期声明
fn func<'a>(a:&'a i32, b:&`a i32){
//<略>
}
这样的声明说明 a 和 b 的生命周期都是'a
,'a
在这里没有实际意义,仅表示一个提示编译器的签名,提示有相同签名的变量有相同的生命周期。
特殊的声明是'static
,表示一直存在,所有的str
常量类型都有静态生命周期。
参考资料
- references-and-borrowing
- lifetime-syntax
- 封面图片:Photo by Toa Heftiba on Unsplash