当我可以使用可变变量绑定时,为什么需要重新绑定/隐藏?



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

let x = a();
let x = b(x);

let mut x = a();
x = b(x);

可变变量绑定允许在this上可变地借用该变量。但是,与可变绑定相比,隐藏是否有一些优势呢?

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


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

我们考虑一个简单的函数:fn hello() -> String; .

当像这样调用这个函数时:

fn main() {
    hello();
}

会发生什么?

函数返回一个String,它被立即丢弃(执行Drop,因为它释放了它的内存)。

结果被删除,因为它没有绑定到变量名,并且语言规则说,如果没有绑定,则可以立即删除1

如果我们绑定这个结果,然而,我们延长了这个值的生命周期,我们可以通过这个绑定访问它…一段时间。

fn main() {
    let value = hello();
    std::mem::drop(value);
    println!("{}", value); // Error: moved out of value
}

这个就是问题所在:在Rust中,值的生命周期与绑定的作用域无关。

一个值甚至不需要在它的绑定退出它的作用域之前被删除:它可以被转移到另一个值(类似于从函数返回)。

fn main() {
    let x;
    {
        let y = hello();
        x = y;
    }
    println!("{}", x);
}

1_ 绑定时发生相同的情况。


那么,现在我们知道绑定和值是不同的,让我们来检查一下这两个代码片段。

第一个影子片段,与你的不同:

fn main() {
    let x = a();
    let x = b();
}

步骤,按顺序:

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

请注意,重新绑定x并不影响先前绑定的值的生命周期。

从技术上讲,它的行为就像b()的结果被绑定到y一样,唯一的例外是,当y在作用域中时,之前的x绑定是不可访问的。

现在,可变代码段:
fn main() {
    let mut x = a();
    x = b();
}

步骤,按顺序:

  • 表达式a()创建一个值,该值绑定到x
  • 表达式b()创建一个值,该值绑定到x,并且删除之前由a()创建的值
  • 删除b()创建的值

再一次,访问前一个值是不可能的,然而,使用遮蔽是暂时不可能的(如果在较小的范围内遮蔽),使用赋值是永远不可能的,因为值被删除了。

我自己找到了一个答案:影子可以改变变量的类型。

let x = get_some_string();
let x = x.smart_parse_int();

最新更新