在计算机编程中,变量的作用域定义了变量可用的区域。例如,
fn main() {
// this variable has scope inside the main function block
let age = 31;
…
}
在这里,age 变量的作用域在 main()
函数的主体 {...}
内,
注意: Rust 中的每个变量都具有在块内有效的作用域。块是由花括号 {}
包围的语句集合。
Rust 中变量作用域的工作原理
让我们通过一个示例来了解变量作用域是如何工作的,
fn main() {
// scope of outer_var variable is inside the main function code block
let outer_var = 100;
// start of the inner code block
{
// scope of inner_var variable is only inside this new code block
let inner_var = 200;
println!("inner_var = {}", inner_var);
}
// end of the inner code block
println!("inner_var = {}", inner_var);
println!("outer_var = {}", outer_var);
}
在这里,如果我们尝试在内部代码块之外打印 inner_var,程序将无法编译,并出现错误。
输出
error[E0425]: cannot find value `inner_var` in this scope --> src/main.rs:13:32 | 13 | println!("inner_var = {}", inner_var); | ^^^^^^^^^ help: a local variable with a similar name exists: `outer_var`
Rust 编译器在内部代码块之外尝试打印变量时找不到作用域内的 inner_var。
要解决此问题,我们可以这样做:
fn main() {
// scope of outer_var variable is inside the main function code block
let outer_var = 100;
// start of the inner code block
{
// scope of inner_var variable is only inside this new code block
let inner_var = 200;
println!("inner_var = {}", inner_var);
println!("outer_var inside inner block = {}", outer_var);
}
// end of the inner code block
println!("outer_var = {}", outer_var);
}
输出
inner_var = 200 outer_var inside inner block = 100 outer_var = 100
我们从外部代码块中移除了 println!("inner_var = {}", inner_var);
,程序现在可以按预期工作。
此外,我们可以在内部代码块中访问 outer_var,因为它的作用域在 main()
函数中。
Rust 中变量作用域的工作方式如下:

Rust 中的变量遮蔽
在 Rust 中,当一个在特定作用域内声明的变量与在外部作用域内声明的变量同名时,这被称为变量遮蔽。
我们可以在同一程序的不同作用域块中使用相同的变量名。
让我们看一个例子:
fn main() {
let random = 100;
// start of the inner block
{
println!("random variable before shadowing in inner block = {}", random);
// this declaration shadows the outer random variable
let random = "abc";
println!("random after shadowing in inner block = {}", random);
}
// end of the inner block
println!("random variable in outer block = {}", random);
}
输出
random variable before shadowing in inner block = 100 random after shadowing in inner block = abc random variable in outer block = 100
在这里,外部块中声明的 random 变量在内部块中被遮蔽了。让我们看看这意味着什么,
let random = "abc";
内部块中的 random 变量值将遮蔽外部块的值,因此内部块将具有 "abc"
的值。但是,内部块之外的 random 变量的值保持不变。
Rust 中的变量冻结
我们可以使用遮蔽和不可变性来冻结 Rust 中的变量。一旦变量被冻结,我们就无法在内部作用域中更改变量的值。
让我们看一个例子。
fn main() {
let mut age = 1;
// start of the inner block
{
// shadowing by immutable age variable
let age = age;
// error, age variable is frozen in this scope
age = 2;
println!("age variable inner block = {}", age);
// age variable goes out of scope
}
// end of the inner block
// age variable is not frozen in outer block
age = 3;
println!("integer variable outer block = {}", age);
}
输出
error[E0384]: cannot assign twice to immutable variable `age` --> src/main.rs:10:9 | 7 | let age = age; | --- | | | first assignment to `age` | help: consider making this binding mutable: `mut age` ... 10 | age = 31; | ^^^^^^^^ cannot assign twice to immutable variable
在上面的示例中,我们将外部块的可变变量 age 赋值给内部作用域中的同一个不可变变量。
fn main() { let mut age = 100; {let age = age;… } … }
通过这样做,我们用一个名为 age
的不可变变量遮蔽了可变变量 age
。
现在,age 变量在内部块中被冻结,因为内部 age 变量指向的值与外部块中的 age 变量指向的值相同。
因此,我们无法在内部块中更改 age 的值,并会遇到错误。
一旦我们退出内部块,age 的值就可以更改。
让我们看看变量冻结示例的工作版本。
fn main() {
let mut age = 100;
{
// shadowing by immutable age variable
let age = age;
println!("age variable inner block = {}", age);
// age goes out of scope
}
// age variable is not frozen in this scope
age = 3;
println!("age variable outer block = {}", age);
}
输出
age variable inner block = 100 age variable outer block = 3