当返回对作用域外值的可变引用的不可变引用时,为什么在作用域结束时丢弃可变引用


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(就足够了,它拥有引用值的所有权。这个模型代表了可变借用的排他性。

基于该模型的推理:在块2中,n是对原始m的引用,而在块1中,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将指向n的副本,该副本在s被丢弃时被丢弃——这是不允许的。如果m是非复制的,则m将被移到s中,这将具有相同的含义。

在块2中,直接借用原始m而不复制它。如果你强制复制,你会得到与块1:相同的错误

let mut m = 10;
let n = {
let m2 = m;
let mut a = &m2;
let b = &a;
&**b
};
println!("{:?}", n);

最新更新