面试题答案
一键面试作用域
- 外层变量
outer_var
:其作用域从定义处开始,到外层代码块结束。例如:
{
let outer_var = 10;
// outer_var 在此处有效
{
// outer_var 在此处仍然有效
}
// outer_var 在此处有效
}
// outer_var 在此处无效
- 内层变量
outer_var
:如果内层代码块中定义了同名变量,其作用域从定义处开始,到内层代码块结束。例如:
{
let outer_var = 10;
{
let outer_var = 20;
// 内层的 outer_var 在此处有效,遮蔽了外层的 outer_var
}
// 内层的 outer_var 在此处无效,外层的 outer_var 重新可见
}
初始化规则
- 外层变量
outer_var
:按照正常的Rust变量初始化规则,需要在使用前初始化。例如:let outer_var: i32;
这样声明而不初始化会报错,应let outer_var = 10;
- 内层变量
outer_var
:同样需要在使用前初始化。它与外层变量同名,但由于作用域不同,内层变量不会干扰外层变量的初始化规则。不过要注意内层变量遮蔽了外层变量,在内层代码块中访问的是内层的outer_var
。
生命周期
- 外层变量
outer_var
:其生命周期从创建开始,到外层代码块结束时结束。只要外层代码块存在,并且没有提前释放(Rust 自动管理内存),outer_var
就一直存在。 - 内层变量
outer_var
:其生命周期从创建开始,到内层代码块结束时结束。它的生命周期完全独立于外层变量,即使内层变量与外层变量同名,内层变量的销毁不会影响外层变量,反之亦然。
Rust编译器处理方式
Rust编译器允许内层代码块定义与外层代码块同名的变量,这种现象称为变量遮蔽(shadowing)。编译器会将内层的变量定义视为一个新的变量,遮蔽外层同名变量。在内层代码块中,所有对 outer_var
的引用都指向内层变量。当离开内层代码块时,内层变量被销毁,外层变量重新可见。这种机制有助于控制变量的作用域和避免意外的变量冲突,同时也遵循Rust的内存安全原则。例如:
fn main() {
let outer_var = 10;
println!("Outer var: {}", outer_var);
{
let outer_var = 20;
println!("Inner var: {}", outer_var);
}
println!("Outer var again: {}", outer_var);
}
上述代码会正确输出:
Outer var: 10
Inner var: 20
Outer var again: 10
编译器清晰地区分了内外层同名变量的作用域、初始化和生命周期,确保代码的正确性和内存安全性。