Chapter 3 of the Rust BookVariables 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接受了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,而是在x第一次绑定到5时调用mut:

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

变量如何(并非真正)避免重新分配的模糊性,似乎与保护绑定到不可变(默认情况下)变量的值的既定目标背道而驰.来自同一章(也包含第Shadowing节):

重要的是,当我们试图

在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_0x_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绝对没有影响,存储位置x_0y_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);
}

它无法编译,因为你不能在它被borrow 时变异x_0.

Rust 关心的是防止不必要的Mutations 效应.这与允许阴影并没有冲突,因为阴影时并没有改变值,只是以其他地方无法观察到的方式改变了特定名称的含义.阴影是一种严格的局部变化.

所以是的,你绝对可以不改变x的值.你要做的是避免名字x所指的东西被改变.最多可以使用clippy之类的值来拒绝将阴影作为线头.

Rust相关问答推荐

重新导出proc宏导致未解决的extern crate错误""

如何使用 list 在Rust for Windows中编译?

亚性状上位性状上的 rust 病伴生型界限

如何在 struct 的自定义序列化程序中使用serde序列化_WITH

Rust类似功能是C++命名空间吗?

为什么Rust不支持带关联常量的特征对象?

为什么RefCell没有与常规引用相同的作用域?

`actix-web` 使用提供的 `tokio` 运行时有何用途?

如何使用 Bincode 在 Rust 中序列化 Enum,同时保留 Enum 判别式而不是索引?

在发布中包含 Rust DLL

注释闭包参数强调使用高阶排定特征界限

Some(v) 和 Some(&v) 有什么区别?

我什么时候应该使用特征作为 Rust 的类型?

不能将 `*self` borrow 为不可变的,因为它也被borrow 为可变的 - 编译器真的需要如此严格吗?

为什么传递 option.as_ref 的行为不同于使用匹配块并将内部映射到 ref 自己?

在单独的线程上运行 actix web 服务器

TcpStream::connect - 匹配武器具有不兼容的类型

Rust 跨同一文件夹中文件的可见性

在 Traits 函数中设置生命周期的问题

为什么 Rust 标准库同时为 Thing 和 &Thing 实现特征?