以下代码报告错误: 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);
}

但以下代码是正确的:


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

推荐答案

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

以下是代码的精简版本,更易于讨论:

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}");
}

让我们将生命周期 分别称为ac,'a'c.因此,f具有类型&'c mut &'a [mut] i32.当我们做b = &**f的时候,可变版本和不变版本之间是有区别的.

在不可变的版本中,我们取消引用f以获得&'a i32.然后我们将该引用copy(这很好,因为共享引用是Copy),并获得类型&'a i32的独立引用.我们可以将这个引用(或它的再borrow 版本&*r)赋给b,因为a的作用域与b的作用域相同.

在可变情况下,我们还取消了对f的引用.然而,我们得到的引用是一个可变引用:&'a mut i32.由于可变引用不是Copy,我们不能将其复制到独立引用.它必须保持在目前的水平,落后于f&'c mut.

然而,我们可以做的是重新borrow 此引用来创建从它派生的引用.但是,当您重新borrow 类型&'a mut &'b mut T的引用时,您无法获得类型&'b mut T的引用,而只能获得类型&'a mut T的引用.否则,您获得的引用可能会超过原始引用的生存期,并且在您没有该引用的权限时存在.

因此,我们得到100,而不是&'a mut i32.bc长寿,所以我们不能将&'c mut i32(或从它创建的共享&'c i32)赋给b.

Rust相关问答推荐

将此字符串转换为由空格字符分隔的空格

在铁 rust 中传递所有权

铁 rust ,我的模块介绍突然遇到了一个问题

为什么TcpListener的文件描述符和生成的TcpStream不同?

try 创建随机数以常量

如何防止Cargo 单据和Cargo 出口发布( crate )项目

在复制类型中使用std::ptr::WRITE_VILAR进行内部可变性的安全性(即没有UnSafeCell)

如何对一个特征的两个实现进行单元测试?

使用 pyo3 将 Rust 转换为 Python 自定义类型

Rust 中的复合 `HashSet` 操作或如何在 Rust 中获得 `HashSet` 的显式差异/并集

在描述棋盘时如何最好地使用特征与枚举

从光标位置旋转精灵

从嵌入式 Rust 中的某个时刻开始经过的时间

如何限制通用 const 参数中允许的值?

当你删除一个存在于堆栈中的值时,为什么 rust 不会抱怨

如何在 Rust 中返回通用 struct

意外的正则表达式模式匹配

深度嵌套枚举的清洁匹配臂

有没有办法隐藏类型定义?

为什么我可以在没有生命周期问题的情况下内联调用 iter 和 collect?