绑定Rust变量会踩什么坑

讲动人的故事,写懂人的代码

3.2 变量绑定的声明和初始化分开

在3.1.1中提到,变量的声明和初始化可以分开。而这也为程序员挖了一个坑,如代码清单3-4所示。

本书代码下载链接为github.com/wubin28/book_LRBACP。本书所有的代码清单,会注明在这个链接中的文件夹位置,以便读者找到相应的没有行号的代码来运行。

下载代码之前,请先安装git。具体的安装步骤,可以询问你最喜欢用的生成式AI聊天工具。

之后,可以运行git clone命令,然后进入文件夹book_LRBACP即能看到所有代码。

代码清单3-4 在初始化完成之前误用变量

rust 复制代码
// 源代码位置:ch03/uninitialized_peril
 1 fn main() {
 3     let x: i32;
 4     if true {
 5         x = 5;
 6     }
 7     // 取消注释下面一行以查看编译错误: 变量`x`在某些执行路径上未初始化
 8     // println!("x的值是: {}", x);
18 }

代码清单3-4所对应的完整源代码,展示了"在初始化完成之前误用变量"的问题,以及如何正确初始化变量。代码分为两部分:一个有潜在问题的部分和一个修复后的部分,都涉及变量的声明和初始化。

第3行声明了一个i32类型的变量x,但没有立即初始化它。

第4-6行:在一个if表达式中初始化x。虽然这里条件始终为truex总会被赋值为5,但编译器却不放过这一点。

第8行被注释掉了。如果取消注释,就会踩坑里。这将导致编译错误,因为编译器认为x在某些执行路径上未初始化。

❗️变量初始化避坑指南
当变量的声明与初始化分开,并使用if表达式进行初始化时,如果无法确保在所有可能的执行路径上都初始化变量,那么编译会报错。

如何修复这个问题?只要在第6行后面加个else表达式,并在表达式里给x再初始化一下,让编译器确信所有执行路径都初始化即可。

3.3 多次绑定同一名称进行变量遮蔽

Rust中的变量遮蔽(variable shadowing),指在同一作用域内使用相同名称声明新变量的能力。新变量会"遮蔽"之前声明的同名变量,之前的变量不再有效。这允许程序员重用变量名。如下所示。

rust 复制代码
fn main() {
    let x = 5;
    let x = x + 1; // 新的x遮蔽了之前的x
    println!("x is {}", x);
}
// 输出:
// x is 6

这个特性在保持变量名简洁的同时,允许程序员在同一作用域的不同阶段,针对同一名称声明不同类型、值或可变性的新变量。需要注意的是,遮蔽和可变性(mutability)是不同的概念。

❗️变量遮蔽避坑指南

遮蔽创建了一个新变量,而非修改旧变量。这个新变量虽与旧变量同名,但可能拥有完全不同的类型、值或可变性。

变量遮蔽虽然有重用变量名的便利,但若使用不当,会让程序员踩什么坑?主要会踩3个坑。

第1个坑是忘记遮蔽更改了变量类型。变量遮蔽能创建不同类型的新变量,但粗心的程序员有时会忘记这一点,继续使用遮蔽前的类型而踩坑(踩坑源代码参见:ch03/shadow_type_amnesia)。

第2个坑是多次更改变量含义的遮蔽,引发困惑。变量遮蔽的本质,是相同的名称来声明新的变量。新的变量的含义在每次声明时,难免会发生变化。当变量的含义变化得过大时,变量名就变成错误的"指路牌",往往让程序员产生误解而踩坑(踩坑源代码参见:ch03/shadowing_maze)。

第3个坑是忘记遮蔽更改了变量可变性。这和第1个坑有点像。在用变量遮蔽绑定新的同名变量时,可以更改变量的可变性。粗心的程序员会忘记这一点而踩坑(踩坑源代码参见:ch03/shadowed_mutability_trap)。

如果喜欢这篇文章,别忘了给文章点个"在看",好鼓励小吾继续写哦~😃

相关推荐
IT专家-大狗37 分钟前
Google Chrome Canary版官方下载及安装教程【适用于开发者与进阶用户】
开发语言·javascript·chrome·ecmascript
唐青枫39 分钟前
Rust cargo 命令行工具使用教程
rust
martian6652 小时前
100道C#高频经典面试题带解析答案——全面C#知识点总结
开发语言·c#
电子连接器CAE与高频分析2 小时前
matlab求和∑函数方程编程?
开发语言·算法·matlab
re1ife2 小时前
Android Studio开发知识:从基础到进阶
android·java·开发语言·android studio
寒雪谷2 小时前
小试牛刀-抽奖程序
开发语言·harmonyos·鸿蒙
满怀10152 小时前
【Python技术生态全景:十大核心应用领域深度解析】
开发语言·python
Asthenia04126 小时前
为什么说MVCC无法彻底解决幻读的问题?
后端
Asthenia04126 小时前
面试官问我:三级缓存可以解决循环依赖的问题,那两级缓存可以解决Spring的循环依赖问题么?是不是无法解决代理对象的问题?
后端