// print:
// string-a
// string-aaabc
fn main() {
let mut a = String::from("string-");
let s = &mut a;
let ss = &mut a; // s goes out of scope here
ss.push('a');
// string-a
println!("{}", ss.clone()); // ss.clone() ==> borrow shared reference, ss(mutable reference) should be gone out of scope. but it still available. why ???
ss.push_str("aa");
let b = &mut (*ss); // borrow '&mut (*ss)' twice to mutable, ss shoudle be gone out of scope. but it still available. why ???
// uncommenting,error(cannot borrow `*ss` as mutable more than once at a time)
// let b = &mut (*ss); ==> first mutable borrow occurs here ==> why?
// ss.push('d'); ==> second mutable borrow occurs here ==> why?
// b.push('b'); ==> first borrow later used here
// why ?
// ss.push('d');
b.push('b');
ss.push('c'); // why? ss still available!
println!("{}", a); // string-aaabc
}
这个例子颠覆了我对所有权和引用范围的理解。我很困惑。 问题就像代码注释
// print:
// string-a
// string-aaabc
fn main() {
let mut a = String::from("string-");
let s = &mut a;
let ss = &mut a; // s goes out of scope here
ss.push('a');
// string-a
println!("{}", ss.clone()); // ss.clone() ==> borrow shared reference, ss(mutable reference) should be gone out of scope. but it still available. why ???
ss.clone
借用ss
,它不获取所有权。当 clone
返回时,它会释放借用,因此 ss
仍然可用。 ss
是独占引用 (&mut
) 而不是共享引用 (&
) 的事实不会改变这里的任何内容。这仅意味着在 ss
返回之前没有人可以使用 clone
,无论如何这是不可能的。
ss.push_str("aa");
let b = &mut (*ss); // borrow '&mut (*ss)' twice to mutable, ss shoudle be gone out of scope. but it still available. why ???
a
ss
独家借用的,因此在 a
被丢弃之前,ss
无法使用。ss
b
独家借用的,因此在 ss
被丢弃之前,b
无法使用。请注意,ss
仅由b
借用,未移动,因此一旦ss
释放借用,b
将再次可用。
// uncommenting,error(cannot borrow `*ss` as mutable more than once at a time)
// let b = &mut (*ss); ==> first mutable borrow occurs here ==> why?
// ss.push('d'); ==> second mutable borrow occurs here ==> why?
// b.push('b'); ==> first borrow later used here
// why ?
// ss.push('d');
b
仍然存在,并拥有
ss
的独占借用,因此无法直接访问 ss
。 b.push('b');
这是我们最后一次使用
b
,因此由于
非词汇生命周期,现在可以删除
b
,并且 ss
再次可用。 ss.push('c'); // why? ss still available!
b
只是借用了
ss
,并没有取得所有权。因此,现在 b
已被删除,借用已释放,并且 ss
再次可用。出于完全相同的原因,一旦 a
被删除,ss
在下一行再次可用: println!("{}", a); // string-aaabc
}