首先,我知道有很多类似的问题,我读过很多讨论,但我仍然不明白我的情况是怎么回事。
struct Test {
x: u32,
}
fn main() {
let mut t = & mut Test { x: 0 };
println!("{}", t.x);
t = & mut Test { x: 1 };
println!("{}", t.x);
}
好的,这会像预期的那样给出一个错误:
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:8:15
|
8 | t = & mut Test { x: 1 };
| ^^^^^^^^^^^^^- temporary value is freed at the end of this statement
| |
| creates a temporary value which is freed while still in use
creates a temporary value which is freed while still in use
-这是正确的,但为什么这个错误不发生在之前?它只发生在&mut
的第二次赋值上,而第一次赋值没有问题。它不应该也创建一个被丢弃的临时值吗?这就是我不明白的地方。
此外,如果我删除mut
,那么一切都运行良好:
fn main() {
let mut t = & Test { x: 0 };
println!("{}", t.x);
t = & Test { x: 1 };
println!("{}", t.x);
}
但是为什么呢?一个不可变的引用仍然是一个引用,它仍然指向一些数据,临时值仍然被丢弃。所以引用应该是无效的。也应该给予错误,但不,它没有。为什么?为什么?
但是,等等,还有更多!如果我为Test
实现Drop
trait:
impl Drop for Test {
fn drop(& mut self) { }
}
现在我又得到了同样的错误,而没有更改main()
中的代码。有什么关系?
1条答案
按热度按时间nszi6y051#
为什么
works在Why is it legal to borrow a temporary?和参考文件中进行了描述:
let
语句中表达式的临时作用域有时会扩展到包含let
语句的块的作用域。当通常的临时作用域太小时,根据某些语法规则,可以这样做。不起作用,因为它不是
let
语句,因此没有资格获得相同的终身促销。允许将临时提升为静态(因为它是不可变的),并且以下内容也符合常量提升的条件:
这样就行了
由于
Drop
实现改变了静态变量和局部变量的语义,因此实现它的任何东西都不符合常量提升的条件,因此问题再次出现(对实现Drop
的东西的引用只符合与可变引用相同的范围扩展)。链接的参考文章包含对所有这些的更全面的解释。