绑定Rust变量会踩什么坑

ops/2024/10/18 18:15:45/

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

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

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

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

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

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

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

rust">// 源代码位置:ch03/uninitialized_peril1 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遮蔽了之前的xprintln!("x is {}", x);
}
// 输出:
// x is 6

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

❗️变量遮蔽避坑指南

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

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

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

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

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

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


http://www.ppmy.cn/ops/124256.html

相关文章

【DataLoom】智能问数 - 自然语言与数据库交互

探索DataLoom的智能问数功能:简化数据库查询 在数据驱动的决策制定中,数据库查询是获取洞察的关键步骤。但是,传统的数据库查询方法往往复杂且技术性强,这限制了非技术用户的使用。DataLoom的智能问数功能正是为了解决这一问题而…

Orecle 迁移 人大金仓数据库 SQL 问题

1. start with ... connect by 语法不兼容 使用 oracle 项目一般使用,start with ... connect by 语法做菜单栏数据查询,该语法在人大金仓数据库提供的可视化工具中可以执行,但在Springboot mybatis 项目中无法执行(版本2.X),通…

Spring Boot集成encache快速入门Demo

1.什么是encache EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点,是 Hibernate 中默认的 CacheProvider。 Ehcache 特性 优点 快速、简单支持多种缓存策略:LRU、LFU、FIFO 淘汰算法缓存数据有两级:内存和磁盘&a…

以FLV解复用为例详解开源库FFmpeg中解复用器的源码逻辑及处理流程

目录 1、FFmpeg简介 2、FLV文件格式介绍 3、注册解复用器 4、解复用器的处理 4.1、AVFormatContext 4.1.1、AVClass 4.1.2、AVOption 4.1.3 AVDictionary—AV字典 4.1.4、AVIOContext 4.1.4.1、URLProtocol 4.1.4.2、AVIOContext的初始化及获取 4.1.5、AVInputF…

【工具】前端js数字金额转中文大写金额

【工具】前端js数字金额转中文大写金额 代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>金额转…

鸿蒙fork()功能

fork功能 上层通过使用fork()函数创建新进程。 fork是什么&#xff1f; #include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h>int main(void) {pid_t pid;char *message;int n;pid fork();if (pid < 0) {perror…

LUCEDA IPKISS Tutorial 77:在版图一定范围内填充dummy

案例分享&#xff1a;在给定的Shape内填充dummy 所有代码如下&#xff1a; from si_fab import all as pdk from ipkiss3 import all as i3 from shapely.geometry import Polygon, MultiPolygon import numpy as np import matplotlib.pyplot as pltclass CellFilledWithCon…

SFML库环境配置

bilibili 下载第三方库 以SFML库为例,到官网SFML (sfml-dev.org)下载对应编译器架构的(如gcc是32位的就安装32位的SFML)对应压缩包解压到指定目录下 添加环境配置 c_cpp_properties.json 一般你配置好vscode中的标准c环境之后,都会有这个文件,c_cpp_properties.json是用来…