以下是我的问题:
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);
}
如果将代码更改如下:
当使用类型为&mut String
的变量s1时,会导致编译错误,因为它没有实现Copy
trait。
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);
}
这段代码将会编译且没有任何错误信息。
当一个引用被传递给函数时,意味着该引用借用
了该值,而不是拥有它。
但在上面的情况中,当s1被传递给 fn c
并立即返回时,s2 借用
了s1,因此在s2生命周期内,s1无法进行解除引用。
那么当s1传递到 fn c
中发生了什么呢?
let s2 =c(s1);
,你可以使用let s2 = &mut *s1;
:引用并非Copy
,但你可以像函数中所做的那样获取新引用。请注意,这不是一个答案:我对导致c
中解引用规则不够清楚。 - Denys Séguret*s1 = String::from("world2");
之后添加println!("{:?}", s2);
,你会得到cannot assign to *s1 because it is borrowed
。所以我猜这可能与 NLL 有关。不过这是一个非常有趣的问题。 - Svetlin Zarevfn c
的情况下重新借用 s1,情况也是一样的:let s2 = &mut *s1;
。所以我猜,在fn c()
的情况下,rustc 在幕后执行了一个重新借用,而在s2 = s1
的情况下,它只是进行了一个move
。相关问题:https://dev59.com/9lgQ5IYBdhLWcg3wRBzK - Svetlin Zarevs2
一个引用类型:let s2: &mut _ = s1;
将会正常工作,因为编译器会推断出在目标被知道是可变引用时重新借用。 - trent