绑定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)。

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

相关推荐
JustHappy3 分钟前
古法编程秘籍(七):互联网到底是什么?把两台电脑怎么说话搞懂就够了
前端·后端·网络协议
yaoxin52112313 分钟前
434. Java 日期时间 API - Period 基于日期的时间段
java·开发语言·python
Hommy8824 分钟前
【剪映小助手】添加图片接口(Add Images)
后端·github·剪映小助手·视频剪辑自动化
凡人叶枫40 分钟前
Effective C++ 条款30:透彻了解 inlining 的里里外外
linux·开发语言·c++·嵌入式开发·effective c++
GetcharZp1 小时前
别再盲目用 OpenCV 读图了,这才是 CV 预处理的终极杀手锏!
后端
学逆向的1 小时前
C++纯虚函数
开发语言·c++·网络安全
程序员二叉1 小时前
【JUC】ThreadLocal底层原理|内存泄漏|弱引用|跨线程传递方案
java·开发语言·面试·职场和发展·juc
程序员二叉1 小时前
【JUC】线程池全套深度详解|参数|流程|拒绝策略|调优|异常处理
java·开发语言·jvm·算法·面试·juc
凡人叶枫2 小时前
Effective C++ 条款22:将成员变量声明为 private
linux·开发语言·c++
Qt程序员2 小时前
掌握 Linux 内核调度:从原理到实现(进程篇)
java·开发语言