当变量在 Rust 中移动时,它会在引擎盖下进行变量阴影吗?

When variables move in rust does it do variable shadowing under the hood?

我想知道当变量从一个作用域移动到另一个作用域时,rust 是否在幕后进行变量遮蔽。

因为当我将变量移动到另一个函数时,可以更改另一个函数的签名以使变量可变,但是当变量 moved/returned 从其他函数返回到 main 时,它不再是不可变的。

我只是对这里发生的事情感到好奇。

fn main() {
    let vec0 = Vec::new(); // immutable by default
    let mut vec1 = foreign_func(vec0); // vec0 has now moved
    // Is foreign_func returning a mutable vector? Because without `mut` keyword vec1 is immutable by default.
    vec1.push(10);
}

fn foreign_func(mut vec: Vec<i32>) -> Vec<i32> { 
    // argument passed for vec is now mutable in this scope.
    // Is this like variable shadowing?
    // let test = 10;
    // let mut test = 20;
    vec.push(20);
    vec
}

没有不可变的Vec,只有变量或借用可以不可变(实际上unique/exclusive,但在Vec的情况下是一样的).

在您的示例中发生的是 移动 Vec 首先从 mainvec0 移动到 foreign_funcvec,然后回到main,这次是vec1。其中一些绑定是 mut 而另一些不是,但这与移动的值无关。事实上,将 Vec 从不可变变量转换为可变变量可以像 let mut vec1 = vec0 一样简单,它编译得很好。

正如 Peter Hall 所指出的,阴影是一个不同的概念:引入一个有意共享现有变量名称的新变量。由于这两个变量具有相同的名称,因此在其范围内只能访问最近的一个。请注意,被隐藏的变量和隐藏它的变量不必具有相同的类型,并且在隐藏时可能会或可能不会发生移动:

fn shadow1(v: Option<Vec<u32>>) {
    // here shadowing moves the old value
    let v = v.unwrap_or_else(Vec::new);
}

fn shadow2(v: Vec<u32>) {
    // here shadowing not accompanied by move
    let v = v.as_slice();
}

当没有移动时,阴影值有可能在操作结束后再次有用。在那种情况下,可以在单独的作用域中引入阴影变量,以便在内部作用域完成后旧值重新出现:

fn shadow3(v: Vec<u32>) {
    {
        let v = v.as_slice();
        // temporarily working with a &[u32] slice, Vec is inaccessible
    }
    // here we have the Vec again
}