rust:变量与可变性
变量与可变性
不可变变量(默认)
在Rust中,变量默认是不可改变的,这带来的好处就是利用 Rust 提供的安全性和简单并发性来编写代码。当变量不可变时,如果赋于其值,就无法改变这个值。例如:
fn main() {let x = 3;println!(”x 的值是: {x}“);x = 6;println!(”x 的值是: {x}“);
}
使用cargo run运行输入如下:
2 | let x = 3;| - first assignment to `x`
3 | println!(”x 的值是: {x}“);
4 | x = 6;| ^^^^^ cannot assign twice to immutable variable|
help: consider making this binding mutable|
For more information about this error, try `rustc --explain E0384`.
error: could not compile `variables` (bin ”variables“) due to 1 previous error
反馈的错误信息是cannot assign twice to immutable variable,不能对不可变变量二次赋值,但如果你试着改变不可变的值,可能会产生bug,如果一部分代码中不可变的值永远也不会改变,而另一部分代码改变了这个值,第一部分代码就有可能以不可预料的方式运行。这种 bug 的起因难以跟踪,尤其是第二部分代码只是有时会改变值。
不过不用担心,Rust 编译器保证,如果声明一个值不可变,它就真的不会变,这意味着你的代码更易于推导。
可变变量
根据以上条件,并不是说变量只能不可变,尽管变量默认是不可变的,但你可以通过添加mut来改变它,这样可以更加方便编写代码,例如:
fn main() {let mut x = 3;println!(”x 的值是: {x}“);x = 5;println!(”x 的值是: {x}“);
}
输出如下:
x 的值是: 3
x 的值是: 5

这表明变量可通过mut,使变量根据需求改变值,无论是不可变性还是可变性,目的都是使代码变得清晰明白。
变量遮蔽(Shadowing)
- 在变量不变性的基础上,我们尝试再引入一个具有相同名称的变量,例子如下:
fn main() {let x = 5;let x = x + 1;println!(”x 的值是: {x}“);
}
输出如下:
x 的值是: 6

由变量的不可变性得出x应该不变的,为何与其不符的值呢?我们引入一个新的概念遮蔽。
定义一个与之前变量相同名字的新变量,我们称第一个变量被第二个变量遮蔽(Shadowing),在Rust编译器中,它只看得到第二个变量,即第二个变量遮蔽了第一个变量,在以后任何使用该变量名的行为都会被认为是第二个变量,直到第二个变量也被其他变量所遮蔽,或者逃离第二个变量的作用域。
- 遮蔽的方式
- 使用相同的变量名
- 重复使用
let关键字
如下所示:
fn main() {let x = 5;let x = x + 1;{let x = x * 2;println!(”作用域里的值是: {x}“);}println!(”x 的值是: {x}“);
}
首先将 x赋值 5 。通过 let创建了一个新变量 x,获取初始值并加 1,这样 x 的值就变成 6 了。然后,在使用花括号创建的内部作用域内,第三个 let语句也遮蔽了 x并创建了一个新的变量,将之前的值乘以 2,x得到的值是 12。当该作用域结束时,内部遮蔽的作用域也结束了,x 又返回到 6。输入结果如下:

作用域里的值是: 12
x 的值是: 6
遮蔽与mut的区别
- 对变量进行二次赋值时,如果没有使用
let关键字,其结果就会报错。通过使用let
语句,我们可以继续用这个值计算,但得出的变量依然是不可变的。 - 使用
let时,实际上是创建一个新变量,再改变数据类型,并且复用这个名字。例如:
let spaces = ” “;let spaces = spaces.len();
第一个 spaces 变量是字符串类型,第二个 spaces 变量是数字类型。遮蔽使我们不必使用不同的名字,如 spaces_str 和 spaces_num;相反,我们可以复用 spaces 这个更简单的名字。然而,如果尝试使用 mut,将会得到一个编译时错误,如下所示:
let mut spaces = ” “;spaces = spaces.len();
这个错误说明,是不能改变变量的类型的。
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
总结
- 优先使用不可变变量:除非确实需要改变值
- 合理使用遮蔽:当需要改变类型或重新赋值时
- 明确意图:使用
mut明确表示这个变量需要改变 - 综合运用,示例:
fn main() {// 不可变变量let name = "Alice";// 可变变量let mut age = 25;age = 26;// 变量遮蔽let age = "twenty-six"; // 类型改变// 在作用域中遮蔽{let age = 30; // 只在当前作用域有效println!("内部 age: {}", age);}println!("外部 age: {}", age); // "twenty-six"
}
Rust 的可变性系统是其内存安全保证的核心部分,通过编译时的严格检查来防止数据竞争和其他常见的内存错误。
