问题描述
如果我打电话:
fn nothing() -> i32{
let x = 2;
let x = 3;
}
我读到一个新的地址分配在堆栈上,旧变量的名称“不可访问”(但未释放吗?)。我收到了不好的信息吗?
为什么Rust不会在堆栈上保留相同部分的内存并对其进行突变?让我们不声明一个常量或静态,那么这是怎么回事?有没有办法在可变阴影(例如指向堆栈)中具有多个句柄?
如果是这样,那么编译器可以执行一次0引用计数检查,并通过一个mut来优化多个let,如果它从未被指向,因为按照定义,只有名称句柄可以使值发生变化?
这仅仅是由于本机多线程和并发安全性设计选择吗?
解决方法
我收到错误信息了吗?
您的信息是正确的。但是您的原始变量可能是借来的,并且可以间接使用,因此它不能简单地无条件地消失:
fn nothing() {
let x = 2;
let p = &x;
let x = 3;
dbg!(*p); //prints 2
}
它与多线程无关。这是一个纯粹的语法功能。从代码生成的角度来看,您的代码与以下代码相同:
fn nothing() -> i32{
let x1 = 2;
let x2 = 3;
//do not use x1 ever again
}
也就是说,阴影不会改变代码的语义。为什么要这样 shadowing 的最简单定义是,它没有什么特别的事情,只是语法上隐藏了先前的名称。
如果要重用堆栈内存,只需使用相同的变量即可:
fn nothing() -> i32{
let mut x = 2;
x = 3;
}
也就是说,如果您的类型不是Drop
,那么您的两个x
很有可能会重用相同的内存。但是我的x1/x2
也是如此。