当我可以进行可变变量绑定时,为什么还需要重新绑定/阴影?

Rom*_*ach 8 rust

当我可以进行可变变量绑定时,为什么还需要重新绑定/阴影?考虑:

let x = a();
let x = b(x);
Run Code Online (Sandbox Code Playgroud)

let mut x = a();
x = b(x);
Run Code Online (Sandbox Code Playgroud)

可变变量绑定允许对此变量进行可变借用.但是,影子比可变绑定有一些优势吗?

Mat*_* M. 14

因为两者的效果完全不同.


要真正理解发生了什么,我们需要从头开始:什么是绑定?绑定是什么意思?

让我们考虑一个简单的功能:fn hello() -> String;.

调用此函数时,如下所示:

fn main() {
    hello();
}
Run Code Online (Sandbox Code Playgroud)

怎么了?

该函数返回a String,它被迅速丢弃(Drop因为它正在执行,从而释放其内存).

结果被删除,因为它没有绑定到变量名,并且语言的规则说如果没有绑定,那么它可以被迅速删除1.

但是,如果我们绑定这个结果,我们会延长这个值的寿命,我们可以通过这个绑定来访问它......一段时间.

fn main() {
    let value = hello();

    std::mem::drop(value);

    println!("{}", value); // Error: moved out of value
}
Run Code Online (Sandbox Code Playgroud)

是当前的问题:在Rust中,值的生命周期独立于绑定的范围.

在绑定退出其范围之前,甚至不需要删除值:它可以转移到另一个(类似于从函数返回).

fn main() {
    let x;
    {
        let y = hello();
        x = y;
    }
    println!("{}", x);
}
Run Code Online (Sandbox Code Playgroud)

1 如果绑定到同样的情况会发生_.


所以,现在我们支持绑定和值不同的事实,让我们检查两个片段.

第一个阴影片段,与您的不同:

fn main() {
    let x = a();
    let x = b();
}
Run Code Online (Sandbox Code Playgroud)

步骤,按顺序:

  • 表达式a()创建一个绑定到的值x
  • 表达式b()创建一个绑定到的值x
  • 创建的值b()被删除
  • 创建的值a()被删除

请注意,x重新绑定的事实不会影响先前绑定的值的生命周期.

从技术上讲,它的行为与b()绑定的结果完全相同y,唯一的例外是在范围内x无法访问先前的绑定y.

现在,可变片段:

fn main() {
    let mut x = a();
    x = b();
}
Run Code Online (Sandbox Code Playgroud)

步骤,按顺序:

  • 表达式a()创建一个绑定到的值x
  • 表达式b()创建一个绑定的值,并删除x先前的值(创建者a())
  • 创建的值b()被删除

再一次,访问前一个值是不可能的,但是在使用阴影的情况下暂时不可能(如果在较小的范围内进行阴影),由于值被删除,因此无法永久地进行分配.

  • 也许只有我这么认为,但这个答案显示了两者的不同以及它们的工作原理;我还没有更深入地理解***为什么***该功能首先内置于该语言中,尤其是当你可以轻松地说“let x = a();”时 let y = b();` 而不是使用阴影来重新绑定 `x` 两次。 (2认同)

Rom*_*ach 9

我发现自己的一个答案:阴影可以改变变量类型.

let x = get_some_string();
let x = x.smart_parse_int();
Run Code Online (Sandbox Code Playgroud)

  • 不仅.你也可以改变mutability(这是常见的用例):`let mut foo = Foo :: new();/*build foo*/let foo = foo; // make foo immutable`. (3认同)
  • @ŁukaszNiemier:请注意,您可以简单地使用块表达式,`let foo = { let mut foo = Foo::new(); ...; 富};` (2认同)