2. 变量与可变性

任务说明

本案例通过三个递进的小程序,演示 Rust 中 let 变量绑定、mut 可变性以及 const 常量的核心语义。完成本案例后,你将能够准确区分“不可变绑定”“可变绑定”和“编译期常量”三者的适用场景。

核心概念与代码实现

Rust 中变量默认不可变(immutable),这是为了提供内存安全与并发安全保证。当需要修改绑定的值时,必须显式使用 mut 关键字声明可变绑定。而 const 定义的是编译期常量,必须标注类型,且不能使用 mut。以下代码完整展示了这三种绑定的定义方式及各自的行为边界。

// 变量与可变性演示
// 文件:variable_mutability.rs

// 编译期常量:必须显式标注类型,值在编译时确定
const MAX_POINTS: u32 = 100_000;

fn main() {
    // 1. 不可变绑定(默认)
    let x = 5;
    println!("x 的值为: {x}");
    // 取消下面注释将导致编译错误:cannot assign twice to immutable variable
    // x = 6;

    // 2. 可变绑定:使用 mut 关键字
    let mut y = 10;
    println!("y 的初始值为: {y}");
    y = 15; // 允许修改
    println!("y 修改后的值为: {y}");

    // 3. 常量使用:通过 const 定义的常量
    println!("常量 MAX_POINTS 的值为: {MAX_POINTS}");

    // 4. 演示变量遮蔽(shadowing):允许复用变量名
    let z = 3;
    let z = z + 1; // 遮蔽前一个 z
    println!("遮蔽后 z 的值为: {z}");

    // 5. 演示不可变绑定的作用域限制
    let outer = 42;
    {
        let inner = 99;
        println!("内部作用域 inner = {inner}");
        // 内部可以访问外部变量
        println!("内部访问 outer = {outer}");
    }
    // 取消下面注释将导致编译错误:cannot find value `inner` in this scope
    // println!("外部访问 inner = {inner}");
    println!("外部 outer = {outer}");
}

编译与运行

将上述代码保存为 variable_mutability.rs,在终端执行以下命令编译并运行:

rustc variable_mutability.rs
./variable_mutability   # Windows 下为 variable_mutability.exe

预期输出

程序运行后,终端将依次打印以下内容(输出顺序与代码执行顺序一致):

x 的值为: 5
y 的初始值为: 10
y 修改后的值为: 15
常量 MAX_POINTS 的值为: 100000
遮蔽后 z 的值为: 4
内部作用域 inner = 99
内部访问 outer = 42
外部 outer = 42

验证方法与判定标准

完成以下三步验证,全部通过即判定本案例掌握:

  1. 编译通过:执行 rustc variable_mutability.rs 无报错,生成可执行文件。
  2. 运行输出匹配:运行程序,观察输出是否与上述“预期输出”完全一致(数值与顺序均需匹配)。
  3. 取消注释验证编译错误:分别取消代码中 x = 6; 和 println!("外部访问 inner = {inner}"); 两处注释,重新编译,确认编译器分别报出 cannot assign twice to immutable variable 和 cannot find value `inner` in this scope 错误。这验证了不可变绑定与作用域规则的真实约束。
Rust 变量绑定与可变性内存布局 编译期常量 (const) MAX_POINTS: u32 100_000 不可变 · 编译期内联 · 必须标注类型 不可变绑定 (let) x: i32 (默认) 5 栈上分配 · 不可重新赋值 · 可遮蔽 可变绑定 (let mut) y: i32 10 → 15 栈上分配 · 可重新赋值 · 需显式声明 作用域与遮蔽 (Shadowing) 示意 外部作用域 let outer = 42; let z = 3; → let z = z + 1; z 被遮蔽为 4,原值 3 被丢弃 内部作用域(块级) let inner = 99; 可访问 outer(外部可见) inner 离开此块即失效,外部不可访问 访问

关键点说明

  • 不可变绑定:let x = 5 后,x 指向的值无法修改,任何赋值尝试都会在编译期被拒绝。
  • 可变绑定:let mut y = 10 允许后续通过 y = 15 改变绑定值,但仅限同一作用域内。
  • 常量:const 在编译期直接内联到使用位置,不占用运行时内存,且必须显式标注类型。
  • 遮蔽:let z = z + 1 创建了一个新绑定,而非修改原值,原值在遮蔽后不可再访问。
  • 作用域:块级作用域({ })内声明的绑定在块结束时自动失效,外部无法访问。