为什么修改未声明为可变的变量时编译器不报错?
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)
要求 x
比 v
寿命更长,因此在 v
之前被声明为 。
对它的需求并不经常出现,但当它出现时,其他解决方案将需要 运行 次检查。
我安装了 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)
要求 x
比 v
寿命更长,因此在 v
之前被声明为 。
对它的需求并不经常出现,但当它出现时,其他解决方案将需要 运行 次检查。