fn main() {
    // block1: fails
    {
        let mut m = 10;

        let n = {
            let b = &&mut m;
            &**b // just returning b fails
        };

        println!("{:?}", n);
    }

    // block2: passes
    {
        let mut m = 10;

        let n = {
            let b = &&m;
            &**b // just returning b fails here too
        };

        println!("{:?}", n);
    }
}

block1失败,错误如下:

error[E0597]: borrowed value does not live long enough
  --> src/main.rs:7:22
   |
7  |             let b = &&mut m;
   |                      ^^^^^^ temporary value does not live long enough
8  |             &**b // just returning b fails
9  |         };
   |         - temporary value dropped here while still borrowed
...
12 |     }
   |     - temporary value needs to live until here

假设内部不可变引用扩展到block2范围之外,而在block1中,内部可变引用总是被删除,即使有外部引用,我的假设是否正确?

推荐答案

在这里,将可变借阅看作一个非Copy struct (下面的代码段中有S个)就足够了,它拥有引用值的所有权.这个模型代表了可变借阅的排他性.

基于此模型的推理:在block2中,n是对原始m的引用,而在block1中,n最终是对可变借阅拥有的m副本的引用.在这两个块中,内部引用都会在let块的末尾被删除,但只有在块1中,这才会导致问题,因为在块1中,删除该内部引用时,n的引用目标仍然属于内部引用.

struct S { m: i32 }
let mut m = 10;

let n = {
    let s = S { m };
    let b = &s;
    &(*b).m
}; // s is dropped

println!("{:?}", n);

在片段中,s以上的人拥有m的副本.参考文献n将指向在删除s时删除的n的副本,这是不允许的.如果m是非复制的,m将被移动到s,这将具有相同的含义.

在block2中,原版m是直接借来的,无需复制.如果强制复制,将得到与block1相同的错误:

let mut m = 10;

let n = {
    let m2 = m;
    let mut a = &m2;
    let b = &a;
    &**b
};

println!("{:?}", n);

Rust相关问答推荐

为什么在Rust struct 中只允许最后一个字段具有动态大小的类型

如何使用字符串迭代器执行查找?

如何在嵌套的泛型 struct 中调用泛型方法?

为什么HashMap::get和HashMap::entry使用不同类型的密钥?

使用占位符获取用户输入

在没有任何同步的情况下以非原子方式更新由宽松原子操作 Select 的值是否安全?

为什么这个闭包没有实现Fn?

如何为整数切片定义一个带有额外函数的特性别名?

`tokio::pin` 如何改变变量的类型?

Rust 打包在 .deb 中

Rust 编译器不统一在 if let 表达式的分支中都 impl Future 的类型

如何在 Rust 的 Hyper 异步闭包中从外部范围正确读取字符串值

Rust:`sort_by` 多个条件,冗长的模式匹配

bcrypt 有长度限制吗?

如何在 Rust 中将 bson::Bson 转换为 Vec

使用 traits 时,borrow 的值不会存在足够长的时间

我的 Axum 处理程序无法编译:未实现 IntoResponse 特征

从现有系列和 map 值创建新系列

如何在 Rust 中创建最后一个元素是可变长度数组的 struct ?

在 Rust 中返回对枚举变体的引用是个好主意吗?