Rust编程基础之变量与可变性

1.Rust变量

在Rust语言中, 变量默认是不可改变的(immutable), 这是Rust提供给我们的众多优势之一, 让我们可以充分利用Rust提供的安全性和简单并发性来编写代码。

当变量不可变时, 一旦值被绑定在一个名称上, 就不能改变这个值。下面是一段代码的例子:

fn main() {let x = 1;println!("The value of x is: {x}");x = 2;println!("The value of x is: {x}");
}

这段代码如果是其它高级语言, 看不出有什么问题, 定义了一个变量,先赋值1,然后打印输出, 再将该值赋值2, 再打印该值的内容。

但如果你使用的是支持Rust开发语言的IDE, 在这段代码中会给出一个错误标识, 将鼠标移到上面,会看到一段错误提示,如图:

错误含义就是不可多次为一个不可变的变量赋新值。

如果我们使用Rust自带的编译器进行编译, Rust会很贴心的告诉我们错误在哪个位置, 错误的原因, 错误怎么纠正,如图:

在上图的提示中, Rust编译器建议我们想改变变量的值, 应该在let后面加上mut关键字, 这样变量就可以被改变了。

修改代码如下:

fn main() {let mut x = 1;println!("The value of x is: {x}");x = 2;println!("The value of x is: {x}");
}

再次编译, 可以看到已经正确打印了变量内容,如图:

2.Rust常量

类似于不可变变量, 常量(constants)是绑定到一个名称的不允许改变的值, 不过常量和变量还是有一定的区别。

首先, 不允许对常量使用mut, 常量不仅默认不可变, 而且总是不可变。声明常量使用const关键字而不是let, 并且必须注明值的类型。

常量可以在任何作用域中声明,包括全局作用域, 这在一个值需要被很多部分的代码用到时很有用。

最后一个区别是,常量只能被设置为常量表达式,而不可以是其它任何只能在运行时计算出的值。

以下是一个常量的声明例子:

const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 *3;

常量的名称是 THREE_HOURS_IN_SECONDS,它的值被设置为 60(一分钟内的秒数)乘以 60(一小时内的分钟数)再乘以 3(我们在这个程序中要计算的小时数)的结果。Rust 对常量的命名约定是在单词之间使用全大写加下划线。编译器能够在编译时计算一组有限的操作,这使我们可以选择以更容易理解和验证的方式写出此值,而不是将此常量设置为值 10,800。

在声明它的作用域之中,常量在整个程序生命周期中都有效,此属性使得常量可以作为多处代码使用的全局范围的值,例如一个游戏中所有玩家可以获取的最高分或者光速。

将遍布于应用程序中的硬编码值声明为常量,能帮助后来的代码维护人员了解值的意图。如果将来需要修改硬编码值,也只需修改汇聚于一处的硬编码值。

3.隐藏

在Rust中,我们可以定义一个与之前变量同名的新变量, 在这种情况下, 称之为第一个变量被第二个隐藏(Shadowing)了, 这意味着当我们使用变量的名称时, 编译器将看到第二个变量。实际上,第二个变量“遮蔽”了第一个变量,此时任何使用该变量名的行为中都会视为是在使用第二个变量,直到第二个变量自己也被隐藏或第二个变量的作用域结束。可以用相同变量名称来隐藏一个变量,以及重复使用let关键字来多次隐藏。

看一段下面的代码:

fn main() {let x = 5;let x = x + 1;{// 进入隐藏作用域let x = x * 2;println!("The value of x in the inner scope is: {x}");}println!("The value of x is: {x}");
}

我们先在代码下个断点, 通过调试状态观察变量值的情况,如图:

从上图中可以看到, 进入花括号作用域后, x 经过计算已经变成了12, 所以第一个打印的应该是12。

如果出了作用域会怎样呢, 继续单步走一下退出作用域,如图:

可以看到, 出了作用域之后, X的值又变成了6, 因此第二个打印语句的结果就是6。

因此最终输出如下:

隐藏与将变量标记为 mut 是有区别的。当不小心尝试对变量重新赋值时,如果没有使用 let 关键字,就会导致编译时错误。通过使用 let,我们可以用这个值进行一些计算,不过计算完之后变量仍然是不可变的。

mut 与隐藏的另一个区别是,当再次使用 let 时,实际上创建了一个新变量,我们可以改变值的类型,并且复用这个名字。例如,假设程序请求用户输入空格字符来说明希望在文本之间显示多少个空格,接下来我们想将输入存储成数字(多少个空格):

let spaces = "   ";
let spaces = spaces.len();

第一个 spaces 变量是字符串类型,第二个 spaces 变量是数字类型。隐藏使我们不必使用不同的名字,如 spaces_strspaces_num;相反,我们可以复用 spaces 这个更简单的名字。然而,如果尝试使用 mut,将会得到一个编译时错误,如下所示:

let mut spaces = "   ";
spaces = spaces.len();

错误提示如下:

4.总结

在本篇文章中, 我们学到以下知识点:

1.Rust变量定义及可变性、不可变性的灵活应用。

2.Rust常量的基本作用域和命名规则。

3.Rust变量的隐藏属性规则、原理和应用。

在下一篇文章中,我们将学习Rust更多的数据类型。包括:整型、浮点型、布尔型、字符类型、元组、数组。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/174893.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Panda3d 介绍

Panda3d 介绍 文章目录 Panda3d 介绍Panda3d 的安装Panda3d 的坐标系统介绍Panda3d 的运行Panda3d 加载一个熊猫父节点和子节点之间的关系 验证Panda3d 的坐标系统X 轴的平移Y 轴的平移Z 轴的平移X 轴的旋转Y 轴的旋转Z 轴的旋转 Panda3D是一个3D引擎:一个用于3D渲染和游戏开发…

[Linux]线程池

[Linux]线程池 文章目录 [Linux]线程池线程池的概念线程池的优点线程池的应用场景线程池的实现 线程池的概念 线程池是一种线程使用模式。线程池是一种特殊的生产消费模型,用户作为生产者,线程池作为消费者和缓冲区。 线程过多会带来调度开销&#xff0c…

Generalized Zero-Shot Learning With Multi-Channel Gaussian Mixture VAE

L D A _{DA} DA​最大化编码后两种特征分布之间的相似性 辅助信息 作者未提供代码

1400*C. Element Extermination(贪心规律)

Problem - 1375C - Codeforces 解析: 可以发现,最左端的数字,无论删除自己还是下一个,这个位置的值都不会变小。 同理,最右端位置的值都不会变大。 所以当最后剩余两个数字的时候,只有左端小于右端数字&…

【经典面试】87 字符串解码

字符串解码 题解1 递归(程序栈)——形式语言自动机(LL(1)) : O(S)另一种递归(直观) 题解2 2个栈(逆波兰式)1个栈(参考官方,但是不喜欢) 给定一个经过编码的字符串,返回它解码后的字符串。 编码规则为: k[encoded_string],表示其中方括号内部的…

深入探究深度学习、神经网络与卷积神经网络以及它们在多个领域中的应用

目录 1、什么是深度学习? 2、深度学习的思想 3、深度学习与神经网络 4、深度学习训练过程 4.1、先使用自下上升非监督学习(就是从底层开始,一层一层的往顶层训练) 4.2、后自顶向下的监督学习(就是通过带标签的数…

文件管理怎么清内存?效率提升一倍

定期清理文件管理可以释放存储空间和提高系统性能。随着时间的推移,手机中可能会存储大量无用的数据,例如缓存、垃圾文件等,导致系统运行缓慢。那么如何清理文件管理的内存呢?下面介绍三种方法。 一、搜索无用的文件夹进行清理 1…

【Bug—eNSP】华为eNsp路由器设备启动一直是0解决方案!

目录 一、项目场景 二、问题描述 三、原因分析 四、解决方案 注意&#

(二开)Flink 修改源码拓展 SQL 语法

1、Flink 扩展 calcite 中的语法解析 1)定义需要的 SqlNode 节点类-以 SqlShowCatalogs 为例 a)类位置 flink/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlShowCatalogs.java 核心方法: Override pu…

高阶数据结构学习 —— 图(1)

文章目录 1、并查集2、了解图3、邻接矩阵4、压缩路径5、基本概念6、邻接表 1、并查集 并查集是一个森林,是由多棵树组成的。这相当于整套数据,分成多个集合。查找有交集的集合们,会把它们合并起来,所以叫并查集。 一开始拿到的是…

电脑突然提示找不到msvcp140.dll怎么办,解决msvcp140.dll丢失的办法

当我们在电脑上运行某些软件或游戏时,可能会遇到一个常见的错误消息:“找不到msvcp140.dll”。出现这样的情况通常意味着系统缺少一个重要的动态链接库文件,而这可能会导致程序无法正常启动。如果你现在遇到了这个问题,哪有可以用…

3D LUT 滤镜 shader 源码分析

最近在做滤镜相关的渲染学习,目前大部分 LUT 滤镜代码实现都是参考由 GPUImage 提供的 LookupFilter 的逻辑,整个代码实现不多。参考网上的博文也有各种解释,参考了大量博文之后终于理解了,所以自己重新整理了一份,方便…

最新Microsoft Edge浏览器如何使用圆角

引入 最近我看了edge官方的文档,里面宣传了edge的最新UI设计,也就是圆角,但是我发现我的浏览器在升级至最新版本之后,却没有圆角 网上有很多人说靠实验性功能即可解锁,但是指令我都试过了,每次都是搜索无结…

OpenLayers入门,OpenLayers从vue的assets资源路径加载TopoJson文件并解析数据叠加到地图上,以加载世界各国边界为例

专栏目录: OpenLayers入门教程汇总目录 前言 本章以加载世界各国边界的TopoJson格式数据为例,讲解如何使用OpenLayers从vue的assets资源路径加载TopoJson文件并解析数据叠加到地图上。 GeoJson介绍 GEOJSON是gis地图中常用的数据格式,制作地图时用于存储各种地理数据,使…

一站式解决安全问题

端玛科技致力于攻克困难的应用软件安全问题,我们的解决方案以安全标准、安全教育和安全风险评估三大支柱为安全SDLC的基础,这三大支柱相互依存,创建了一个可重复的、安全的软件开发生态系统。 主要业务范围:关注整个软件开发过程…

基于SpringBoot的在线笔记系统

技术介绍 🔥采用技术:SpringSpringMVCMyBatisJSPMaven 🔥开发语言:Java 🔥JDK版本:JDK1.8 🔥服务器:tomcat 🔥数据库:mysql 🔥数据库开发工具&…

七、【图像添加水印】

文章目录 一、制作水印1、先新建图层2、新建文字图层并调好水印文字的大小与角度3、添加图层样式4、添加定义图案 二、添加水印 一、制作水印 1、先新建图层 2、新建文字图层并调好水印文字的大小与角度 3、添加图层样式 1、打开“描边” 2、选择“颜色” 4、添加定义图案 二…

spring-代理模式

代理模式 一、概念1.静态代理2.动态代理 一、概念 ①介绍 二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标 方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不…

Java SE 学习笔记(十八)—— 注解、动态代理

目录 1 注解1.1 注解概述1.2 自定义注解1.3 元注解1.4 注解解析1.5 注解应用于 junit 框架 2 动态代理2.1 问题引入2.2 动态代理实现 1 注解 1.1 注解概述 Java 注解(Annotation)又称Java标注,是JDK 5.0引入的一种注释机制,Java语…

C语言 指针进阶笔记

p和*p: 如图&#xff0c;p是指针&#xff0c;指针存放着地址&#xff0c;打印出来应该是数组的值 *p是指针里里面的元素 #include<stdio.h> int main() {int a1;int b2;int c3;int p[3]{a,b,c};printf("%d",*p); return 0; } 那么现在的打印结果应该为数组的…