gpt4 book ai didi

variables - 在 Rust 中, "shadowing"和 "mutability"有什么区别?

转载 作者:行者123 更新时间:2023-11-29 08:32:08 24 4
gpt4 key购买 nike

Chapter 3 of the Rust Book , Variables and Mutability,我们在这个主题上进行了几次迭代,以演示 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 对阴影 变量的处理,我们可以简单地这样做来更改仍然“不可变”的 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 绑定(bind)到 5:

fn main() {
let mut x = 5;
println!("The value of x is {}", x);
x = 6;
println!("The value of x is {}", x);
}

这种在如何(不是真正地)保护变量免于重新分配方面的歧义似乎与保护绑定(bind)到不可变(Rust 默认)变量的值的既定目标背道而驰。来自同一章(其中还包含 Shadowing 部分):

It’s important that we get compile-time errors when we attempt to change a value that we previously designated as immutable because this very situation can lead to bugs. If one part of our code operates on the assumption that a value will never change and another part of our code changes that value, it’s possible that the first part of the code won’t do what it was designed to do. The cause of this kind of bug can be difficult to track down after the fact, especially when the second piece of code changes the value only sometimes.

In Rust, the compiler guarantees that when you state that a value won’t change, it really won’t change. That means that when you’re reading and writing code, you don’t have to keep track of how and where a value might change. Your code is thus easier to reason through.

如果我可以通过对 let 的足够无辜的调用来回避我的不可变 x 的这个重要特性,为什么我需要 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_0x_1)。第二个 let 只是重新绑定(bind)名称 x 以引用存储位置 x_1x_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。

关于variables - 在 Rust 中, "shadowing"和 "mutability"有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54270851/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com