问题描述
这是我的问题:
fn main() {
let mut s = String::from("hello");
let s1 = &mut s;
let s2 = s1;
*s2 = String::from("world1");
*s1 = String::from("world2");
println!("{:?}",s);
}
这会导致编译错误,因为 s1 的类型 &mut String
没有实现 copy
特征。
但是如果我改变代码如下:
fn c(s: &mut String) -> &mut String {
s
}
fn main() {
let mut s = String::from("hello");
let s1 = &mut s;
let s2 = c(s1);
*s2 = String::from("world1");
*s1 = String::from("world2");
println!("{:?}",s);
}
编译时不会出现任何错误信息。
我知道当一个引用传递给一个函数时,它意味着引用borrows
值而不是拥有它。
但是在上面的情况下,似乎当 s1 被传递给 fn c
并立即返回时, s2 borrowed
s1 所以 s1 不能除非 s2 超出其生命周期范围,否则不会取消引用。
那么当 s1 被传递到 fn c
时发生了什么?
解决方法
根据@Denys Séguret 的提示,我猜当 s1 传递给 fn C
时,Rust 核心将参数 s1
编译为类似 &mut *s1
,所以有一个不可变的 s1 借用。
这就是为什么如果我们把
*s2 = String::from("world1");
后面
*s1 = String::from("world2");
Rust 会告诉我们:
assignment to borrowed `*s1`
当 s2 超出它的生命周期范围时,s1 不再借用,因此 s1 可以再次取消引用。
但我不太确定这是否是一个正确的解释。