提问人:杨尚山 提问时间:8/30/2023 最后编辑:E_net4杨尚山 更新时间:8/30/2023 访问量:71
这个例子颠覆了我对所有权和参考范围的理解
This example subverts my understanding of ownership and reference scope
问:
// 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
}
这个例子颠覆了我对所有权和引用范围的理解。我很困惑。 问题就像代码注释
答:
1赞
Jmb
8/30/2023
#1
// 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
}
0赞
fwqaaq
8/30/2023
#2
首先,变体和引用是两个不同的东西。一般来说,当你使用完一个变体时,rust 会自动为你删除该变量。
let s = &mut a; // s dropped, because it's not used afterwards.
clone:仅供参考
ss
let b = &mut (*ss);
在这里,您不是借用变量,而是获取原始引用,即保存的原始指针元数据:ss
a
ss
b --> &mut a ss --> &mut a
- 但是,当您使用可变借用时,可能会出现问题。
let b = &mut (*ss); // ------- // | b.push('b'); // ------ // variant `b` was dropped // in here, you can just use `ss`
如果你把它写成这样,这让你感到困惑,那么
//...
ss.push('c'); // cannot borrow `*ss` as mutable more than once at a time second mutable borrow occurs hererustcClick for full compiler diagnostic
b.push('b'); // `b` was not dropped
//...
评论