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

2023-10-30 05:45

本文主要是介绍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更多的数据类型。包括:整型、浮点型、布尔型、字符类型、元组、数组。

这篇关于Rust编程基础之变量与可变性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/305965

相关文章

Python基础文件操作方法超详细讲解(详解版)

《Python基础文件操作方法超详细讲解(详解版)》文件就是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位,文件的核心操作就是读和写,:本文主要介绍Python基础文件操作方法超详细讲解的相... 目录一、文件操作1. 文件打开与关闭1.1 打开文件1.2 关闭文件2. 访问模式及说明二、文件读写1.

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

C#基础之委托详解(Delegate)

《C#基础之委托详解(Delegate)》:本文主要介绍C#基础之委托(Delegate),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 委托定义2. 委托实例化3. 多播委托(Multicast Delegates)4. 委托的用途事件处理回调函数LINQ

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

Rust中的注释使用解读

《Rust中的注释使用解读》本文介绍了Rust中的行注释、块注释和文档注释的使用方法,通过示例展示了如何在实际代码中应用这些注释,以提高代码的可读性和可维护性... 目录Rust 中的注释使用指南1. 行注释示例:行注释2. 块注释示例:块注释3. 文档注释示例:文档注释4. 综合示例总结Rust 中的注释

Rust格式化输出方式总结

《Rust格式化输出方式总结》Rust提供了强大的格式化输出功能,通过std::fmt模块和相关的宏来实现,主要的输出宏包括println!和format!,它们支持多种格式化占位符,如{}、{:?}... 目录Rust格式化输出方式基本的格式化输出格式化占位符Format 特性总结Rust格式化输出方式

Rust中的Drop特性之解读自动化资源清理的魔法

《Rust中的Drop特性之解读自动化资源清理的魔法》Rust通过Drop特性实现了自动清理机制,确保资源在对象超出作用域时自动释放,避免了手动管理资源时可能出现的内存泄漏或双重释放问题,智能指针如B... 目录自动清理机制:Rust 的析构函数提前释放资源:std::mem::drop android的妙

Rust中的BoxT之堆上的数据与递归类型详解

《Rust中的BoxT之堆上的数据与递归类型详解》本文介绍了Rust中的BoxT类型,包括其在堆与栈之间的内存分配,性能优势,以及如何利用BoxT来实现递归类型和处理大小未知类型,通过BoxT,Rus... 目录1. Box<T> 的基础知识1.1 堆与栈的分工1.2 性能优势2.1 递归类型的问题2.2

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应