rust - 当返回对范围外值的可变引用的不可变引用时,为什么在范围结束时丢弃可变引用?

标签 rust mutable dereference borrowing

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 结构(下面代码段中的S)就足够了,它拥有引用值的所有权。该模型代表了可变借用的排他性。

基于此模型的推理:在 block2 中 n 是对原始 m 的引用,而在 block1 中 n 最终将成为一个对可变借用所拥有的 m 副本的引用。在这两个 block 中,内部引用都在 let block 的末尾被丢弃,但只有在 block1 中这会导致问题,因为在 block1 中,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 将指向 n 的副本,当 s 被删除时,该副本被删除 - 不允许。如果 m 是非 Copy,则 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 - 当返回对范围外值的可变引用的不可变引用时,为什么在范围结束时丢弃可变引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51591381/

相关文章:

oop - 在 Rust 中编写 getter/setter 属性

string - 如何处理字符串比较?

compiler-errors - 尽管受到限制,但值(value)还不够长

python - 我的递归函数(填充树结构)在每次循环/调用期间添加到根节点

arrays - python中有可变的二进制数组吗?

c++ - std::sort 指针容器

Android应用程序因空指针取消引用而崩溃?

c - 结构体和指向指针的指针

Rust 的 proc 宏的 C++ 替代品

python - python3 可变属性是否共享?