【问题标题】:Why doesn't the compiler report an error when a variable not declared as mutable is modified?为什么修改未声明为可变的变量时编译器不报告错误?
【发布时间】:2017-09-17 02:26:54
【问题描述】:

我安装了 Rust 1.13 并尝试过:

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

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

【问题讨论】:

  • 这是延迟初始化,不是突变。
  • Rust 1.16 是 Rust 的当前版本,几周后应该会发布 1.17。保持最新状态是值得的。

标签: variables syntax compilation rust mutable


【解决方案1】:

您所写的内容与以下内容相同:

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 更可能在此处使用面向表达式的语法:let x = if condition { 1 } else if other_condition { 10 } else { 100 };。在这些示例中不需要延迟初始化。
  • @MatthieuM。确实如此。但是,如果某些条件分支内部有不同的副作用,那看起来会很奇怪。在那种情况下,我认为这种形式会更惯用。
【解决方案2】:

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

  • mutation 是关于更改现有变量的值,
  • 延迟初始化是关于在某一时刻声明一个变量,然后再对其进行初始化。

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


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

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

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

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

在 Rust 中,借用检查器将验证引用不能超过它所引用的值,从而防止悬空引用。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 2013-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-03
    • 1970-01-01
    相关资源
    最近更新 更多