为什么修改未声明为可变的变量时编译器不报错?

Why doesn't the compiler report an error when a variable not declared as mutable is modified?

我安装了 Rust 1.13 并尝试了:

fn main() {
    let x: u32;
    x = 10; // no error?
}

当我编译这个文件时有一些警告,但没有错误。因为我没有将 x 声明为 mut,所以 x = 10; 不应该导致错误吗?

您所写的内容等同于:

let x: u32 = 10;

此后编译器将不允许您改变它:

let x: u32;
x = 10;
x = 0; // Error: re-assignment of immutable variable `x`

请注意,如果您尝试使用未初始化的变量,则会出现编译器错误:

let x: u32;
println!("{}", x); // Error: use of possibly uninitialized variable: `x`

如果您想根据运行时条件以不同方式初始化变量,此功能将非常有用。一个天真的例子:

let x: u32;
if condition {
    x = 1;   
} else if other_condition {
    x = 10;
} else {
    x = 100;
}

但是如果有可能它没有初始化,它仍然会出错:

let x: u32;
if condition {
    x = 1;   
} else if other_condition {
    x = 10;
} // no else
println!("{:?}", x); // Error: use of possibly uninitialized variable: `x`

如前所述,这不是突变,而是延迟初始化:

  • 突变是关于改变现有变量的值,
  • 延迟初始化是关于在某一时刻声明一个变量,然后再初始化它。

Rust 编译器会在编译时跟踪变量是否有值,因此与 C 不同,不存在意外使用未初始化变量(或与 C++ 不同,从中移出的变量)的风险。


使用延迟初始化最重要的原因是范围

fn main() {
    let x;
    let mut v = vec!();

    {
        x = 2;
        v.push(&x);
    }

    println!("{:?}", v);
}

在 Rust 中,借用检查器将验证引用不能比它引用的值长寿,从而防止出现悬空引用。

这意味着 v.push(&x) 要求 xv 寿命更长,因此在 v 之前被声明为

对它的需求并不经常出现,但当它出现时,其他解决方案将需要 运行 次检查。