下面的代码运行正确。
{
let a = &mut 3;
*a = 4;
assert_eq!(*a, 4);
}
以下也运行。
{
let a = Some(&3);
let mut b = a.unwrap();
assert_eq!(a.unwrap(), &3);
}
但以下内容无法编译。
{
let a = Some(&mut 3);
assert_eq!(*a.unwrap(), 3);
}
错误是:
40 | let a = Some(&mut 3);
| ^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
41 | assert_eq!(*a.unwrap(), 3);
| - borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
为什么 Rust 编译器以不同的方式对待这些引用,前两段代码可以使引用的生命不仅仅是临时的,而最后一段却不能?
这是 Rust 中的一个概念,称为暂时延长寿命。不过,临时生命周期的延长是有一些规则的。任何时候借用临时文件都不会发生这种情况; a 右侧的表达式let
语句需要是所谓的“扩展表达式”。上面链接的文档的这一部分巧妙地解释了您问题中的第一个和第三个示例:
所以借用表达式&mut 0
, (&1, &mut 2)
, and Some { 0: &mut 3 }
都是扩展表达式。借款于&0 + &1
and Some(&mut 0)
不是:后者在语法上是函数调用表达式。
由于表达式分配给a
在第三个示例中,不是扩展表达式,临时变量的生存期不会超出 let 语句,这会导致生存期问题。
为什么这适用于Some(&3)
然后?因为持续推广:
将价值表达提升为'static
当表达式可以写入常量并借用时,就会出现槽,并且可以在最初写入表达式的地方取消引用该借用,而无需更改运行时行为。
由于你一成不变地借用,Rust 会分配一个隐藏的、静态的i32
并借用它,给你一个Option<&'static i32>
,这显然对于程序本身的整个生命周期都有效。从技术上讲,这并不是临时的寿命延长,因为在i32
被提升为具有静态生命周期,它不再是临时的。
它基本上与此等效(除了HIDDEN
没有名字):
static HIDDEN: i32 = 3;
let a = Some(&HIDDEN);
let mut b = a.unwrap();
assert_eq!(a.unwrap(), &HIDDEN);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)