Rust中具有可变阴影的堆栈分配内存会发生什么?

问题描述

如果我打电话:

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也是如此。