跳转到内容

第 2 章 变量与赋值

在其他编程语言里,变量声明和赋值几乎不需要专门花篇幅讲解:声明一个变量,用 = 放进一个值,后面随时读取或替换。但在学 Rust 时,许多人刚写下前几行 let 和 =,就会连续遇到「变量失效」「Copy 与 Move」「不加 mut 连方法都不让调」等编译报错。

原因已经在第一章揭晓了:在带 GC 的语言里,= 只管复制值或对象引用,内存什么时候回收全由运行时兜底;而在 Rust 里,每一行 let 和 = 都在编译期交接或触发第一章推导出的释放责任。

这一章不再使用伪代码。我们直接打开编译器,围绕最基础的 let 与 = 分三步推进:

  • 第一步:首次绑定(let x = ...)——创建新变量并接手初值。从第一个可运行程序出发,核对同一个 = 在整数、String 与引用(&T)上为什么会分出复制、移动与借用三条路。
  • 第二步:重新赋值(x = ...)——更新同一个已有变量。拆解 let mut 放开的两项权限,并顺着编译器的状态追踪回答:当新值换入时,变量原本持有的旧值去了哪里。
  • 第三步:同名遮蔽(再写一次 let x = ...)——创建同名新变量。对比重新赋值与遮蔽的边界,通过实验验证:被同名新变量遮住的旧值,究竟有没有当场释放。

读完这一章,面对一段十来行的真实 Rust 代码,不需要死记编译器错误码,你应该能逐行回答三个问题:

  1. 这是哪个动作:这一行是在创建新变量(首次 let)、更新已有变量(重新赋值),还是用同名新变量遮蔽旧变量?
  2. 右侧怎么交接:等号右侧的值是发生了复制、移动,还是只借用了地址?
  3. 旧值何时释放:当前哪些变量依然有效?每一块堆内存由哪个变量负责,是在赋值那一行当场释放,还是等到作用域结束(})时释放?