Rust 中的生命周期:mut 数据借用

huangapple go评论56阅读模式
英文:

Lifetimes in Rust: mut data borrowed

问题

以下代码报告了一个错误:借用的值寿命不够长

fn main() {
    let e = 100;
    let mut a = (1,);
    let mut b = (&e,);
    {
        let mut c = (&mut a, &mut b);
        let f = &mut c;
        f.1 .0 = &(f.0 .0);
    }
    println!("{:?}", b);
}

但以下代码是正确的:


fn main() {
    let e = 100;
    let a = (1,);
    let mut b = (&e,);
    {
        let mut c = (&a, &mut b);
        let f = &mut c;
        f.1 .0 = &(f.0 .0);
    }
    println!("{:?}", b);
}

为什么?!!

第一个代码的完整错误消息:

error[E0597]: `c` does not live long enough
  --> src/main.rs:7:17
   |
6  |         let mut c = (&mut a, &mut b);
   |             ----- binding `c` declared here
7  |         let f = &mut c;
   |                 ^^^^^^ borrowed value does not live enough
8  |         f.1 .0 = &f.0 .0;
9  |     }
   |     - `c` dropped here while still borrowed
10 |     println!("{:?}", b);
   |                      - borrow later used here

For more information about this error, try `rustc --explain E0597`.
英文:

The following code reports an error:
borrowed value does not live long enough

fn main() {
    let e = 100;
    let mut a = (1,);
    let mut b = (&e,);
    {
        let mut c = (&mut a, &mut b);
        let f = &mut c;
        f.1 .0 = &(f.0 .0);
    }
    println!("{:?}", b);
}

But the following code is correct:


fn main() {
    let e = 100;
    let a = (1,);
    let mut b = (&e,);
    {
        let mut c = (&a, &mut b);
        let f = &mut c;
        f.1 .0 = &(f.0 .0);
    }
    println!("{:?}", b);
}

Why?!!

Full error message for the first code:

error[E0597]: `c` does not live long enough
  --> src/main.rs:7:17
   |
6  |         let mut c = (&mut a, &mut b);
   |             ----- binding `c` declared here
7  |         let f = &mut c;
   |                 ^^^^^^ borrowed value does not live long enough
8  |         f.1 .0 = &f.0 .0;
9  |     }
   |     - `c` dropped here while still borrowed
10 |     println!("{:?}", b);
   |                      - borrow later used here

For more information about this error, try `rustc --explain E0597`.

答案1

得分: 2

这是因为共享引用是Copy的,而可变引用不是。

以下是您的代码的简化版本,更容易讨论:

fn main() {
    let mut a = 1;
    let b;
    {
        let mut c = &mut a;
        // 或者:
        let mut c = &a;
        let f = &mut c;
        b = &**f;
    }
    println!("{b}");
}

让我们将ac的生命周期分别称为'a'c。因此,f的类型是&'c mut &'a [mut] i32。当我们执行b = &**f时,在可变和不可变版本之间存在差异。

在不可变版本中,我们对f进行解引用,得到&'a i32。然后,我们复制这个引用(这是可以的,因为共享引用是Copy),并得到一个类型为&'a i32的独立引用。我们可以将这个引用(或它的重新借用版本&*r)分配给b,因为a的生命周期与b相同。

在可变情况下,我们也对f进行解引用。但是,我们得到的引用是可变引用:&'a mut i32。由于可变引用不是Copy,我们不能将它复制到一个独立的引用中。它必须留在原地,在f&'c mut后面。

然而,我们可以重新借用此引用以创建一个从中派生的引用。但是,当您重新借用类型为&'a mut &'b mut T的引用时,您无法获得类型为&'b mut T的引用,只能获得&'a mut T。否则,您获得的引用可能会超出原始引用的生命周期,并且在您没有权限的情况下存在。

因此,我们得到了**&'c mut i32**,而不是&'a mut i32b的生命周期超出了c,因此我们不能将&'c mut i32(或从中创建的共享&'c i32)分配给b

英文:

This is because shared references are Copy, while mutable references are not.

Here's a trimmed down version of your code, which is easier to discuss:

fn main() {
    let mut a = 1;
    let b;
    {
        let mut c = &mut a;
        // Or:
        let mut c = &a;
        let f = &mut c;
        b = &**f;
    }
    println!("{b}");
}

Let's call the lifetimes of a and c 'a and 'c respectively. Therefore, f has type &'c mut &'a [mut] i32. When we do b = &**f, there is a difference between the mutable and immutable version.

In the immutable version, we dereference f to get &'a i32. We then copy this reference (which is fine because shared references are Copy), and get a freestanding reference of type &'a i32. We can assign this reference (or the reborrowed version of it, &*r) to b, because a has the same scope b has.

In the mutable case, we also dereference f. However, the reference we get is a mutable reference: &'a mut i32. Since mutable references are not Copy, we cannot copy it to a freestanding reference. It has to stay where it is, behind the &'c mut of f.

What we can do, however, is to reborrow this reference to create a reference descended from it. However, when you reborrow a reference of type &'a mut &'b mut T, you cannot get a reference of type &'b mut T, only &'a mut T. Otherwise, the reference you got could outlive the original reference, and exist while you have no permission for such reference.

Therefore, we get &'c mut i32, and not &'a mut i32. b outlives c, so we cannot assign a &'c mut i32 (or a shared &'c i32 created from it) to b.

huangapple
  • 本文由 发表于 2023年5月24日 21:12:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76323931.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定