变量和可变性

“Storing Values with Variables“ 部分,则默认情况下, 变量是不可变的。这是 Rust 为您提供的众多提示之一 您的代码以一种利用安全性和轻松并发的方式 Rust 优惠。但是,您仍然可以选择将变量设置为可变。 让我们探讨一下 Rust 如何以及为什么鼓励你支持不变性,以及为什么 有时您可能想要选择退出。

当变量是不可变的时,一旦值绑定到名称,就无法更改 那个值。为了说明这一点,在 使用 .cargo new variables

然后,在新的 variables 目录中,打开 src/main.rs 并替换其 代码替换为以下代码,该代码暂时无法编译:

文件名: src/main.rs

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

使用 保存并运行程序。您应该会收到一条错误消息 关于 Immutability 错误,如以下输出所示:cargo run

$ cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
error[E0384]: cannot assign twice to immutable variable `x`
 --> src/main.rs:4:5
  |
2 |     let x = 5;
  |         - first assignment to `x`
3 |     println!("The value of x is: {x}");
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable
  |
help: consider making this binding mutable
  |
2 |     let mut x = 5;
  |         +++

For more information about this error, try `rustc --explain E0384`.
error: could not compile `variables` (bin "variables") due to 1 previous error

此示例说明编译器如何帮助您查找程序中的错误。 编译器错误可能令人沮丧,但实际上它们只意味着您的程序 尚未安全地执行您希望它执行的作;它们并不意味着您是 不是一个好的程序员!有经验的 Rustacean 仍然会遇到编译器错误。

您收到错误消息是因为您尝试为 im可变变量分配第二个值。cannot assign twice to immutable variable `x`x

当我们尝试更改 值被指定为 Immutable,因为这种情况可能会导致 错误。如果我们代码的一部分在假设值将 never change 并且我们代码的另一部分更改了该值,这是可能的 代码的第一部分不会执行其设计目的。原因 这种错误在事后可能很难追踪,尤其是 当第二段代码仅偶尔更改值时。锈蚀 compiler 保证当你声明一个值不会改变时,它真的 不会更改,因此您不必自己跟踪它。因此,您的代码是 更容易推理。

但是可变性可能非常有用,并且可以使代码编写起来更方便。 尽管变量默认是不可变的,但你可以通过以下方式使它们可变 在变量名称前面添加,就像您在 Chapter 中所做的那样 2. 添加也传达 intent 通过指示代码的其他部分 将更改此变量的值。mutmut

例如,让我们将 src/main.rs 更改为以下内容:

文件名: src/main.rs

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

现在运行程序时,我们得到这个:

$ cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.30s
     Running `target/debug/variables`
The value of x is: 5
The value of x is: 6

我们可以将绑定到 from 的值更改为 when is 使用。最终,决定是否使用可变性取决于您和 取决于您认为在特定情况下最明显的内容。x56mut

常数

与不可变变量一样,常量是绑定到 name 和 不允许更改,但常量之间存在一些差异 和变量。

首先,不允许与 constants 一起使用。常量不仅仅是 immutable - 它们始终是不可变的。使用 keyword 而不是 keyword 来声明常量,并且必须对值的类型进行批注。我们将在下一节 “数据类型” 中介绍类型和类型注释,因此无需担心细节 马上。只需知道您必须始终对类型进行注释。mutconstlet

常量可以在任何范围内声明,包括全局范围,这使得 它们对于代码的许多部分需要了解的值很有用。

最后一个区别是常量只能设置为常量表达式 而不是只能在运行时计算的值的结果。

下面是一个常量声明的示例:

#![allow(unused)]
fn main() {
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
}

常量的名称为 ,其值设置为 将 60(一分钟内的秒数)乘以 60(数字 of minutes / / 1 小时) 除以 3 (我们想要在此 程序)。Rust 对常量的命名约定是使用全部大写的 单词之间的下划线。编译器能够评估一组有限的 作,这允许我们选择在 这样更容易理解和验证,而不是设置此常量 的值设置为 10,800。请参阅 Rust 参考 中关于 constant 的部分 evaluation 有关可以使用哪些作的更多信息 在声明常量时。THREE_HOURS_IN_SECONDS

常量在程序运行的整个时间内都有效,在 他们被宣布了。此属性使常量对 程序的多个部分可能需要了解的应用程序域 关于,例如游戏中任何玩家允许的最大点数 earn,或光速。

将整个程序中使用的硬编码值命名为常量在 将该值的含义传达给代码的未来维护者。它还 有助于在代码中只有一个位置,如果 hardcoded 值需要在未来更新。

阴影

正如您在章节中的猜谜游戏教程中看到的那样 2 中,您可以声明一个 与上一个变量同名的 new 变量。Rustacean 说, 第一个变量被第二个变量遮蔽,这意味着第二个变量 variable 是编译器在使用变量名称时将看到的内容。 实际上,第二个变量会掩盖第一个变量,以 变量名称添加到自身,直到它本身被隐藏或范围结束。 我们可以通过使用同一变量的名称并重复 关键字的使用方法如下:let

文件名: src/main.rs

fn main() {
    let x = 5;

    let x = x + 1;

    {
        let x = x * 2;
        println!("The value of x in the inner scope is: {x}");
    }

    println!("The value of x is: {x}");
}

此程序首先绑定到值 。然后,它通过重复 来创建一个新变量,取原始值并添加 的值是 。然后,在使用 curly 创建的内部作用域中 brackets 中,第三个语句也会隐藏并创建一个新的 变量,将前一个值乘以得到值 。 当该范围结束时,内部阴影结束并返回到 。 当我们运行这个程序时,它将输出以下内容:x5xlet x =1x6letx2x12x6

$ cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s
     Running `target/debug/variables`
The value of x in the inner scope is: 12
The value of x is: 6

隐藏与标记变量不同,因为我们会得到一个 编译时错误,如果我们不小心尝试在没有 使用关键字。通过使用 ,我们可以执行一些转换 在一个值上,但让变量在这些转换具有 已完成。mutletlet

和 shadowing 之间的另一个区别是,因为我们是 当我们再次使用关键字时,可以有效地创建一个新变量 更改值的 type (类型),但重复使用相同的名称。例如,假设我们的 程序要求用户显示他们希望某些文本之间有多少个空格 输入空格字符,然后我们想将该输入存储为数字:mutlet

fn main() {
    let spaces = "   ";
    let spaces = spaces.len();
}

第一个变量是字符串类型,第二个变量 是数字类型。因此,影子使我们不必提出 不同的名称,例如 和 ;相反,我们可以重用 更简单的名称。但是,如果我们尝试为此使用,如图所示 在这里,我们将收到一个编译时错误:spacesspacesspaces_strspaces_numspacesmut

fn main() {
    let mut spaces = "   ";
    spaces = spaces.len();
}

错误说我们不允许改变变量的类型:

$ cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
error[E0308]: mismatched types
 --> src/main.rs:3:14
  |
2 |     let mut spaces = "   ";
  |                      ----- expected due to this value
3 |     spaces = spaces.len();
  |              ^^^^^^^^^^^^ expected `&str`, found `usize`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `variables` (bin "variables") due to 1 previous error

现在我们已经探索了变量的工作原理,让我们看看它们 可以有。

本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准