Rust - 变量
不管学什么语言好像都得从变量开始,不过只需要懂得大概就可以了。
但在Rust里不先把变量研究明白后面根本无法进行…
变量绑定
变量赋值❌
变量绑定✔️
Rust中没有“赋值”一说,而是称为绑定。
int a = 3; //C中的变量赋值
a = 3; //python中的变量赋值
var a = 3; //JavaScript中的变量赋值
let foo = 3; //Rust中的变量绑定
这里就涉及 Rust 最核心的原则——所有权,简单来讲,任何内存对象都是有主人的,而且一般情况下完全属于它的主人,绑定就是把某个内存对象绑定给一个变量,让这个变量成为它的主人(在这种情况下,该对象之前的主人就会丧失对该对象的所有权)。
变量的可变性
Rust 的变量在默认情况下是不可变的。这是 Rust 语言的特性之一,有助于提升安全和性能。而通过 mut 关键字,即可以指定某个变量为可变的。
// 导入 io 模块,其中包含了处理输入输出的标准库
use std::io;fn main() {// 声明不可变变量 foo,开辟内存对象(值为1)并绑定给它let foo = 1; //编译器进行类型推断,这里推断出是int类型// 声明另一个不可变变量 bar// 开辟新的内存对象(并将 foo 绑定的值 1 拷贝进去),然后绑定给bar// 不可变变量在定义时(内存对象在开辟时)就需要进行值的绑定let bar = foo;// 检查 bar 绑定值是否为数字 1if bar == 1{ 这里的 println! 整体是一个宏,功能为打印一行文字println!("绑定成功")}
}
在上面的例子中,变量 foo和 bar 均为不可变变量,一旦为它绑定值,就不能再进行修改。
选择可变还是不可变,更多的还是取决于实际使用场景,例如不可变可以带来安全性,但是丧失了灵活性和性能,而可变变量最大的好处就是使用上的灵活性和性能上的提升。
// 导入 io 模块,其中包含了处理输入输出的标准库
use std::io;fn main() {println!("我要读取输入");println!("请输入:");// 使用 mut 关键字声明可变变量 rece,类型为 String// 并通过 String 类型内置的默认构造函数初始化为空字符串let mut rece = String::new(); //编译器从右值推断变量是string类型// 使用 io 模块下的 stdin().read_line 方法从标准输入读取一行内容到 rece 变量(绑定的内存)中// rece 需要是可变变量,(根本原因是 rece 绑定的内存需要可变)因为要按照用户输入内容进行修改// 使用 & 是因为此处传递的是参数变量绑定的内存而并非是内存中的值,这样子方便可以在程序的任何位置进行修改// 使用 expect 函数处理错误,如果发生错误则打印“无法读取行”io::stdin().read_line(&mut rece).expect("无法读取行");// 打印读取到的输入内容// {} 是占位符,输出的是后面变量的值。(多个{}就按顺序对应多个变量)println!("你输入的是:{}", rece);
}
在上面的例子中,rece 为一个可变变量,它的值可以进行修改。
这种做法是为了避免无法预期的错误发生在我们的变量上:一个变量往往被多处代码所使用,其中一部分代码假定该变量的值永远不会改变,而另外一部分代码却无情的改变了这个值,在实际开发过程中,这个错误是很难被发现的,特别是在多线程编程中。
变量未使用引起的错误
如果你创建了一个变量却不在任何地方使用它,Rust 通常会给你一个警告,因为这可能会是个 BUG。但是有时创建一个不会被使用的变量是有用的,比如你正在设计原型或刚刚开始一个项目。这时你希望告诉 Rust 不要警告未使用的变量,为此可以用下划线作为变量名的开头:
fn main() {//let foo;//let bar;//像上面这样如果变量定义了但不使用,就会发生警告let _foo;let _bar;//像上面这样,告诉编译器这两个变量是故意不使用的,就不会警告
}
变量遮蔽特性
Rust 允许声明相同的变量名,在后面声明的变量会“遮蔽”掉前面声明的,如下所示:
fn main() {let x = 5; //不可变变量,绑定的内存不可更改,内存的值不可更改。//假设绑定的内存对象为1号// 在main函数的作用域内对之前的x进行遮蔽let x = x + 1; //新的同名不可变变量进行遮蔽//绑定了新的内存对象,假设为2号,该内存对象中的值为(1号内存对象中存储的值+1)//这一行后面相同作用域的程序中,x都指代的是2号内存对象{// 在当前的花括号作用域内,对上面最近的x进行遮蔽let x = x * 2;println!("The value of x in the inner scope is: {}", x);}println!("The value of x is: {}", x);
}
这个程序首先将数值 5 绑定到 x,然后通过重复使用 let x = 来遮蔽之前的 x,并取原来的值加上 1,所以 x 的值变成了 6。第三个 let 语句同样遮蔽前面的 x,取之前的值并乘上 2,得到的 x 最终值为 12。当运行此程序,将输出以下内容:
The value of x in the inner scope is: 12
The value of x is: 6
注意: 这和 mut 声明可变变量的使用是不同的。第二个 let 生成了完全不同的新变量,因为它开辟了新的内存对象,两个变量只是恰好拥有同样的名称,但底层的内存对象是不同的。而 mut 声明的变量,可以修改同一个内存地址上的值,并不会产生新的内存对象。
变量遮蔽的用处在于,如果你在某个作用域内无需再使用之前的变量(在被遮蔽后,无法再访问到之前的同名变量),就可以重复的使用变量名字,而不用绞尽脑汁去想更多的名字。
变量遮蔽不仅可以作用于相同类型的变量,而且可以方便我们在改变变量类型的情况下仍然使用同样的名字:
//将输入的字符串转换成数字
fn main(){println!("输入一个大于0的数字");let mut guess = String::new();//guess为可变变量,绑定的内存不可更改,内存存储的值可更改//从这里往后的guess都是string类型io::stdin().read_line(&mut guess).expect("无法读取行");// 报错:string不能和int进行比较// if guess > 0 {// print!("数字大于0!")// }// 类型转换,绑定新的内存对象,内存类型是i32类型(int类型),可以进行比较// guess.trim().parse() 将字符串转换为数字,用guess绑定的新内存对象存储// 同名不同内存let guess:i32 = guess.trim().parse().expect("转换失败");//从这里往后的guess都是i32类型if guess > 0 {print!("数字大于0!");}
}
// 思考:为什么上面例子中的这句代码不能写成下面这样,进行类型推断?
let guess = guess.trim().parse().expect("转换失败");// 因为可变变量只有一块内存,内存类型是在声明时确定的,并且一旦声明,其类型就不能改变,类型推断也不行。
// guess已经绑定了string类型的内存对象
// 把一个数字存给string类型的内存对象是不允许的
// 错误原因是进行了错误类型赋值。
// 要改变可变变量的类型,就要靠(注明了类型的变量遮蔽)来实现。
不可变变量:内存不可改,内存的值不可改。
可变变量:内存不可改,内存的值可改。
相关文章:
Rust - 变量
不管学什么语言好像都得从变量开始,不过只需要懂得大概就可以了。 但在Rust里不先把变量研究明白后面根本无法进行… 变量绑定 变量赋值❌ 变量绑定✔️ Rust中没有“赋值”一说,而是称为绑定。 int a 3; //C中的变量赋值 a 3; //python中的…...
【Linux】压缩脚本、报警脚本
一、压缩搅拌 要求: 写一个脚本,完成如下功能 传递一个参数给脚本,此参数为gzip、bzip2或者xz三者之一; (1) 如果参数1的值为gzip,则使用tar和gzip归档压缩/etc目录至/backups目录中,并命名为/backups/etc…...
用Flask打造一个大模型智能问答WEB网站
目前已经有很多类似GPT的大模型开源,可以提供类似ChatGPT的智能问答功能。我也基于这些开源模型,用Flask来建立一个智能问答网站,可以方便用户建立自己的ChatGPT系统。 这个网站需要提供用户登录功能,对已登录的用户,可以在网站上提出问题,并由大模型处理后返回答案。演…...
学习python第三天
一.数据类型 1.获取数据类型 x 10 print(type(x))""" 输出 <class int> """2.复数类型(complex)详解 复数(Complex)是 Python 的内置类型,直接书写即可。换句话说,…...
(M)UNITY三段攻击制作
三段攻击逻辑 基本逻辑: 人物点击攻击按钮进入攻击状态(bool isAttack) 在攻击状态下, 一旦设置的触发器(trigger attack)被触发,设置的计数器(int combo)查看目前攻击…...
PHP的线程安全与非线程安全模式选哪个
曾经初学PHP的时候也很困惑对线程安全与非线程安全模式这块环境的选择,也未能理解其中意。近来无意中看到一个教程对线程安全(饿汉式),非线程安全(懒汉式)的描述,虽然觉得现在已经能够很明了透彻…...
asdf安装不同版本的nodejs和yarn和pnpm
安装asdf 安装nodejs nodejs版本 目前项目中常用的是14、16和18 安装插件 asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git asdf plugin-add yarn https://github.com/twuni/asdf-yarn.git可以查看获取所有的nodejs版本 asdf list all nodejs有很多找…...
Spring的事件监听机制
这里写自定义目录标题 1. 概述(重点)2. ApplicationEventMulticaster2.1 SimpleApplicationEventMulticaster2.2 AbstractApplicationEventMulticaster 3. ApplicationListener3.1 注册监听器3.2 自定义 4. SpringApplicationRunListeners 1. 概述&#…...
Zookeeper分布式命名服务实战
目录 分布式命名服务 分布式API目录 分布式节点的命名 分布式的ID生成器 分布式的ID生成器方案: 基于Zookeeper实现分布式ID生成器 基于Zookeeper实现SnowFlakeID算法 分布式命名服务 命名服务是为系统中的资源提供标识能力。ZooKeeper的命名服务主要是利用Z…...
DEV-C++ ege.h库 绘图教程(六)
一、前情回顾 DEV-C ege.h库 绘图教程(一) DEV-C ege.h库 绘图教程(二) DEV-C ege.h库 绘图教程(三) DEV-C ege.h库 绘图教程(四) DEV-C ege.h库 绘图教程(五)…...
MySQL原理(一)架构组成之物理文件组成
目录 一、日志文件 1、错误日志 Error Log 1.1、作用: 1.2、开启关闭: 1.3、使用 2、二进制日志 Binary Log & Binary Log Index 2.1、作用: 2.2、开启关闭: 2.3、Binlog还有一些附加选项参数 (1&#x…...
代码随想录算法训练营第三十七天 | 738.单调递增的数字、 968.监控二叉树
题目链接:738.单调递增的数字 文章讲解:代码随想录 738.单调递增的数字讲解 视频讲解:贪心算法,思路不难想,但代码不好写!LeetCode:738.单调自增的数字 思路和解法 题目: 当且仅当每个相邻位…...
【Django-ninja】django-ninja的hello world
django-ninja简介 Django Ninja是一个用于使用Django和Python 3.6类型提示构建API的Web框架。 主要特点: 易用性:旨在易于使用和直观。 高性能执行:由于Pydantic和异步支持,具有非常高的性能。 编码效率高:类型提…...
ArrayList集合初始化长度是多少,初始化的时候分配内存空间吗
ArrayList一旦初始化,在内存中就会分配空间吗 是的,当ArrayList在Java中初始化时,即使它没有添加任何元素,也会立即分配内存空间。具体来说,对于默认构造函数创建的ArrayList(即不指定初始容量)…...
C语言数组:从入门到进阶
前言: 在这篇博客中,我们将学习如何使用C语言数组的基本知识。数组是C语言中的一种重要数据结构,它允许我们存储一系列相同类型的数据。我们将讨论数组的定义、初始化、访问元素、遍历数组以及数组的应用场景。此外,我们还将通过…...
9.回文数
回文数 将整型转换为字符型反转前一半是否等于后一半将数字本身反转输入一个整数 x,如果 x是一个回文整数,返回 true;否则,返回 false 。 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 例如,121 是回文,而 123 不是。 将整型转换为字符型 反转…...
一分钟在SpringBoot项目中使用EMQ
先展示最终的结果: 生产者端: RestController RequiredArgsConstructor public class TestController {private final MqttProducer mqttProducer;GetMapping("/test")public String test() {User build User.builder().age(100).sex(1).address("世界潍坊渤…...
SOME/IP 协议介绍(七)传输 CAN 和 FlexRay 帧
SOME/IP 不应仅用于传输 CAN 或 FlexRay 帧。但是,消息 ID 空间需要在两种用例之间进行协调。 传输 CAN/FlexRay 应使用完整的 SOME/IP 标头。 AUTOSAR Socket-Adapter 使用消息 ID 和长度来构建所需的内部 PDU,但不会查看其他字段。因此,必…...
与数组相关经典面试题
𝙉𝙞𝙘𝙚!!👏🏻‧✧̣̥̇‧✦👏🏻‧✧̣̥̇‧✦ 👏🏻‧✧̣̥̇:Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - :来于“云”的“羽球人”。…...
数据结构与算法面试系列-02
1. 一个整数,它加上100后是一个完全平方数,加上168又是一个完全平方数,请问该数是多少? 程序分析:在10万以内判断,先将该数加上100后再开方,再将该数加上168后再开方,如果开方后的结果满足如下条件,即是结果。请看具体分析: 程序代码如下: package com.yoodb.uti…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
