在《Rust Book》第 3 章,变量和可变性中,我们对这个主题进行了几次迭代,以演示 Rust 中变量的默认、不可变行为:
fn main() {
let x = 5;
println!("The value of x is {}", x);
x = 6;
println!("The value of x is {}", x);
}
哪个输出:
error[E0384]: cannot assign twice to immutable variable `x`
--> src/main.rs:4:5
|
2 | let x = 5;
| -
| |
| first assignment to `x`
| help: make this binding mutable: `mut x`
3 | println!("The value of x is {}", x);
4 | x = 6;
| ^^^^^ cannot assign twice to immutable variable
但是,由于 Rust 对
shadowing 变量的采用,我们可以简单地这样做来更改“不可变”的值 x
:
fn main() {
let x = 5;
println!("The value of x is {}", x);
let x = 6;
println!("The value of x is {}", x);
}
哪个输出(跳过细节):
The value of x is 5
The value of x is 6
有趣的是,这段代码也会生成上面的两行作为输出,尽管事实上我们没有调用
let
,而是在第一次
mut
绑定到
x
时调用
5
:
fn main() {
let mut x = 5;
println!("The value of x is {}", x);
x = 6;
println!("The value of x is {}", x);
}
如何(并非真正)保护变量免于重新分配的这种模糊性似乎与保护绑定到不可变值(Rust 默认情况下)变量的既定目标相矛盾。来自同一章(还包含
阴影部分):
当我们尝试这样做时,我们会遇到编译时错误,这一点很重要 更改我们之前指定为不可变的值,因为这 任何情况都可能导致错误。如果我们的代码的一部分运行在 假设一个值永远不会改变,而我们的另一部分 代码更改了该值,代码的第一部分可能是 不会做它设计的事情。造成此类错误的原因可以 事后很难追查,尤其是当第二次发生时 一段代码仅有时会更改值。如果我可以通过对在 Rust 中,编译器保证当你声明一个值时 不会改变,真的不会改变。这意味着当你 阅读和编写代码,您不必跟踪如何以及 值可能会改变的地方。因此你的代码更容易推理 通过。
x
的足够无辜的调用来回避我的不可变
let
的这个重要功能,为什么我需要
mut
?有没有什么方法可以让
x
变得不可变,这样就没有
let x
可以重新分配它的值?
fn main() {
let x = 5; // x_0
println!("The value of x is {}", x);
let x = 6; // x_1
println!("The value of x is {}", x);
}
在此示例中,有一个名称(
x
)和两个存储位置(
x_0
和
x_1
)。第二个
let
只是重新绑定名称
x
来引用存储位置
x_1
。
x_0
存储位置完全不受影响。
fn main() {
let mut x = 5; // x_0
println!("The value of x is {}", x);
x = 6;
println!("The value of x is {}", x);
}
在此示例中,有一个名称 (
x
) 和一个存储位置 (
x_0
)。
x = 6
赋值是直接改变存储位置
x_0
的位。您可能会说它们做同样的事情。如果是这样,你就错了:
fn main() {
let x = 5; // x_0
let y = &x; // y_0
println!("The value of y is {}", y);
let x = 6; // x_1
println!("The value of y is {}", y);
}
输出:
The value of y is 5
The value of y is 5
这是因为更改
x
所指的存储位置对
x_0
绝对没有影响,
y_0
包含指向的存储位置。然而,
fn main() {
let mut x = 5; // x_0
let y = &x; // y_0
println!("The value of y is {}", y);
x = 6;
println!("The value of y is {}", y);
}
这无法编译,因为借用时你无法改变
x_0
。Rust 关心的是防止不必要的突变影响
通过参考文献观察到。这与允许阴影并不冲突,因为当您进行阴影时,您并没有更改值,您只是以一种在其他任何地方都无法观察到的方式更改了特定名称的含义。阴影是一个严格的局部变化。
所以是的,你绝对可以保持x
的值不被改变。您不能做的是保持
x
所指的名称不被更改。最多,您可以使用类似
clippy
之类的东西来拒绝阴影作为 lint。