题目
Rust 变量遮蔽与可变性的区别
信息
- 类型:问答
- 难度:⭐
考点
变量遮蔽,可变性,作用域
快速回答
关键区别:
- 可变性 (mut):修改同一内存位置的值
- 变量遮蔽 (Shadowing):创建同名新变量,原变量被隐藏
- 遮蔽允许改变类型,可变性要求类型一致
代码示例:let x = 5; // 不可变
let mut y = 3; // 可变
let x = "hello"; // 遮蔽(类型改变)
y = 10; // 直接修改值
解析
核心概念对比
Rust 有两种修改变量值的方式:
- 可变性 (mut):使用
mut关键字声明可变绑定,可在同类型下修改值 - 变量遮蔽 (Shadowing):使用
let重新声明同名变量,创建新绑定(可改变类型)
代码示例分析
fn main() {
// 基础示例
let x = 5; // 不可变绑定
let x = x + 1; // 遮蔽:创建新变量x
{
let x = x * 2; // 作用域内遮蔽
println!("内部作用域: {}", x); // 输出 12
}
println!("外部作用域: {}", x); // 输出 6
// 类型变更示例
let spaces = " ";
let spaces = spaces.len(); // 允许:string → usize
// let mut spaces_mut = " ";
// spaces_mut = spaces_mut.len(); // 错误!类型不匹配
}原理说明
- 内存模型:
- 可变变量:始终引用同一内存地址
- 遮蔽变量:每次
let都创建新内存空间
- 作用域规则:遮蔽只在当前作用域有效,离开作用域后恢复原绑定
最佳实践
- 优先使用不可变绑定,增强安全性
- 需要修改值时:
- 同类型修改 → 用
mut - 需改变类型或重新初始化 → 用遮蔽
- 同类型修改 → 用
- 避免在深层嵌套中过度使用遮蔽,降低可读性
常见错误
// 错误1:尝试修改不可变变量
let score = 100;
score = 90; // 编译错误!
// 错误2:误以为遮蔽能修改原变量
let count = 1;
{
let count = "one"; // 仅在此块内有效
}
println!("{}", count); // 仍是整数1
// 错误3:混淆 mut 和遮蔽
let mut value = 10;
let value = "text"; // 合法但危险:原可变绑定被永久隐藏扩展知识
- 编译器行为:遮蔽创建新变量时,旧变量在作用域内仍存在但无法访问
- 与重赋值的区别:
- 重赋值:
mut_var = new_value(需同类型) - 遮蔽:
let var = new_value(可跨类型)
- 重赋值:
- 性能影响:遮蔽可能增加栈内存分配,但在释放作用域后自动回收