这个例子颠覆了我对所有权和引用范围的理解

问题描述 投票:0回答:2
// 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
}

这个例子颠覆了我对所有权和引用范围的理解。我很困惑。 问题就像代码注释

rust scope mutable ownership
2个回答
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
投票
    首先,变体和引用是两个不同的东西。一般来说,当您使用完某个变体后,Rust 会自动为您删除该变量。
  1. let s = &mut a; // s dropped, because it's not used afterwards.

  2. 克隆:仅供参考
  3. ss

    
    

  4. 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`
    
    
  5. 如果你像下面这样写,这让你很困惑,那么

//... 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 //...

© www.soinside.com 2019 - 2024. All rights reserved.