当前位置: 首页 > news >正文

Rust开发——变量、静态变量与常量

1.变量

在 Rust 中,类型安全是通过静态类型系统来实现的。变量绑定默认情况下是不可变的(immutable)。

在 Rust 中声明一个变量时,默认情况下它是不可变的。例如:

fn main() {let x :i32 = 5; // 这是一个不可变绑定,默认情况下不可改变其值// x = 10; // 这将导致编译错误,因为 x 是不可变的
}

类型推断,i32是可选的

在上面例子中,x 被声明为一个不可变绑定,并初始化为 5。如果试图修改 x 的值(例如尝试将 x 的值改变为 10),将会导致编译错误,因为变量默认情况下是不可变的。

为了允许变量可变,可以使用 mut 关键字来显式地声明一个可变的绑定:

fn main() {let mut y = 5; // 使用 mut 关键字声明可变绑定y = 10; // 这是合法的,因为 y 是可变的println!("The value of y is: {}", y); // 输出 y 的值
}

使用了 mut 关键字来声明一个可变的绑定 y,然后成功将 y 的值修改为 10

2.类型推断

在 Rust 中,编译器会根据变量的使用方式来推断变量的类型。

fn main() {let x = 5; // 编译器根据赋值来推断 x 的类型为 i32let y = 3.14; // 编译器根据赋值来推断 y 的类型为 f64let sum = x + y; // 编译器根据 x 和 y 的使用来推断 sum 的类型println!("The sum is: {}", sum); // 输出 sum 的值
}

编译器根据赋值来推断 x 的类型为 i32y 的类型为 f64。然后,当 xy 作为操作数相加时,编译器会根据其使用来推断 sum 的类型。在这种情况下,sum 的类型会被推断为 f64,因为它是 i32f64 类型的混合运算结果。Rust 的类型推断功能允许编写更加简洁且灵活的代码,但也保持了类型安全。

值得注意的是,Rust 编译器可以根据变量声明和用法的约束来推断类型。像这样声明的变量并不是某种动态的“任意类型”,可以容纳任何数据。这种声明所生成的机器代码与显式声明类型的代码完全相同。只是编译器完成了这个转换。

下面的代码告诉编译器将某种泛型容器中的内容进行复制,而代码本身并没有显式地指定包含的类型,而是使用 _ 作为占位符:

fn main() {let mut container = Vec::new(); // Rust 根据使用推断出 container 的类型为 Vec<_>container.push(5); // 向向量中添加一个 i32 类型的元素container.push(3.14); // 向向量中添加一个 f64 类型的元素for element in container {println!("Element: {}", element);}
}

container 被初始化为一个空的向量 Vec<_>。下划线 _ 是一个占位符,告诉编译器根据插入向量的元素推断类型。在这种情况下,container 是一个可以容纳不同类型元素的向量(根据插入的元素类型推断出 i32f64)。

Rust 根据容器的使用推断出其类型,并允许其容纳不同类型的元素。但是,一旦推断出特定类型,容器的类型就固定了,除非另有规定,否则不会接受不同类型的元素。

3. 静态变量

静态变量在整个程序执行期间都会存在,并且不会发生移动(move)。

在 Rust 中,静态变量(static variables)拥有 'static 生命周期,它们在程序启动时被初始化,并且在整个程序的生命周期内保持不变。这些变量存储在程序的静态存储区域中,因此它们不会被销毁或移动。这意味着静态变量的生存周期与整个程序的生命周期相同。

由于静态变量的生命周期是 'static,因此其持续时间长达整个程序的运行期间,所以它们不会被移动。在 Rust 中,静态变量的引用可以安全地传递并在整个程序中使用,因为它们的生命周期不会结束或改变。

static BANNER: &str = "Welcome to RustOS 3.14";fn main() {println!("{BANNER}");
}

静态变量在使用时并不会被内联,并且具有实际关联的内存位置。这对于不安全编程和嵌入式代码非常有用,并且这些变量在整个程序执行期间都存在。当全局范围的值不需要对象标识时,通常更倾向于使用 const

由于静态变量可以从任何线程访问,因此它们必须是 Sync 的。可以通过 Mutexatomic 或类似的方式实现内部可变性(interior mutability)。也可以有可变的静态变量,但它们需要手动进行同步,因此对它们的任何访问都需要使用不安全的代码。我们将在关于不安全 Rust 的章节中探讨可变的静态变量。

4.常量(const)

常量在编译时被求值,它们的值会在使用的地方被内联。
在 Rust 中声明一个常量时,编译器会在编译期间计算常量的值,并且将该值内联到代码中使用该常量的地方。这意味着编译器会将常量的实际值直接替换到代码中,而不是在运行时进行计算。这种内联有助于提高代码的效率,并且保证了常量在运行时是不可变的。

例如:

const VALUE: i32 = 42;fn main() {let x = VALUE * 2; // 编译器会将 VALUE * 2 替换为 42 * 2,这个值会在编译期间被计算println!("The value of x is: {}", x);
}

VALUE * 2 的计算结果会在编译时被替换为 84,并且这个值会在运行时被直接使用。这种行为确保了常量在编译期间被求值,并且在编译生成的机器代码中直接被替换。

  • 常量(使用 const 声明)在使用时会被内联,其值会直接替换到代码中。
  • 标记为 const 的函数可以在编译时调用以生成常量值。尽管这些函数可以在运行时被调用,但其主要目的是在编译期间进行计算,生成常量值。

如果使用过C++编程度,在Rust 中的 conststatic时可以理解为:

  • const 在语义上类似于 C++ 的 constexpr。它代表着编译时常量,其值在编译期就已经确定,并且在运行时是不可变的。常量通常用于表示在程序运行期间不会变化的固定值。
  • 相比之下,static 更类似于 C++ 中的 const 或可变的全局变量。static 提供了对象标识:在内存中的地址以及对于具有内部可变性的类型(例如 Mutex<T>)所需的状态。它在整个程序执行期间存在,并且可以被多个线程访问。
  • 在大多数情况下,不太需要在运行时计算常量值,但有时它会比使用 static 更安全。使用 const 可以确保在编译时就确定了值,而 static 在一定程度上可能会引入运行时变化的可能性。
  • 可以通过 std::thread_local 宏创建 thread_local 数据。这种数据是每个线程独有的,每个线程都有自己的一份拷贝,因此线程间不会共享该数据。这对于在多线程环境下需要独立的数据拷贝时非常有用。

5.变量作用域与隐藏变量

在 Rust 中,可以使用作用域隐藏来重新定义同名变量,无论是来自外部作用域还是同一作用域的变量。

fn main() {let a = 5; // 创建变量 a{let a = "hello"; // 在新作用域中重新定义了同名变量 a,隐藏了外部作用域中的 aprintln!("Inner scope: {}", a); // 输出新作用域中的 a,值为 "hello"} // 这里的 a 超出了内部作用域的范围println!("Outer scope: {}", a); // 输出外部作用域中的 a,值为 5,因为内部作用域中的 a 不再可见
}

内部作用域中重新定义的 a 变量隐藏了外部作用域中的同名变量 a。在内部作用域中重新定义的 a 只在该作用域内可见,超出该作用域后,再次访问 a 时会得到外部作用域中的值。这种方式允许你在同一作用域中使用相同名称的变量进行重新定义,而不会产生冲突。

在 Rust 中,变量隐藏与变量的可变性是两种不同的概念。通过变量隐藏,重新定义的同名变量在同一作用域内会覆盖之前定义的变量,但它们的内存位置会同时存在,且都可以使用相同的名称,具体取决于代码中的位置。

变量隐藏允许重新定义具有相同名称的变量,并且新定义的变量可以拥有不同的类型。一开始,变量隐藏可能看起来有些晦涩,但它对于在 .unwrap() 之后保留值非常方便。

以下代码演示了为什么编译器不能简单地在重新定义一个作用域内的不可变变量时重用内存位置,即使类型没有发生变化。

fn main() {let x: i32 = 5;println!("Original x: {}", x);{let x: i32 = 10; // 在新的作用域内重新定义了同名变量 x,类型仍为 i32println!("Inner x: {}", x); // 输出内部作用域的 x,值为 10} // 这里的 x 超出了内部作用域的范围println!("Outer x: {}", x); // 输出外部作用域的 x,值为 5,因为内部作用域中的 x 不再可见let x: &str = "hello"; // 在同一作用域内,将 x 重新定义为字符串类型println!("New x: {}", x); // 输出重新定义的 x,值为 "hello"
}

在上面例子中,重新定义的 x 变量在内部作用域中隐藏了外部作用域中的同名变量 x,但它们的内存位置并不相同。即使类型没有发生变化,重新定义的 x 仍然会分配新的内存空间。这说明了变量隐藏与可变性不同,虽然它们都涉及变量值的改变,但是变量隐藏会重新分配内存,而不是简单地改变值。

相关文章:

Rust开发——变量、静态变量与常量

1.变量 在 Rust 中&#xff0c;类型安全是通过静态类型系统来实现的。变量绑定默认情况下是不可变的&#xff08;immutable&#xff09;。 在 Rust 中声明一个变量时&#xff0c;默认情况下它是不可变的。例如&#xff1a; fn main() {let x &#xff1a;i32 5; // 这是一个…...

javascript Math相关计算取值属性方法

*向上取整【只要有小数就+1】 Math.ceil(3.14); // 4 *向下取整【有小数就舍弃】 Math.floor(3.14); // 3 parseInt(3.14); // 3 // 常用于字符串类型的数字转为十进制的数据 四舍五入【小数点后部分】 Math.round(11.5)); //12 Math.round(-11.5)); //-11 取两数…...

git reset hard,mixed,soft

首先&#xff0c;我们得了解git reset命令的形式之一&#xff1a; git reset [<mode>] [<commit>] 此命令的作用是恢复HEAD分支到<commit>位置&#xff0c;并根据<mode>决定是否恢复index file和working tree。恢复是指将staging area和working tree…...

Cookie与Session知识

目录 一.Cookie与Session的发展史 1.Cookie的发展史 2.Session的发展史 3.Cookie和Session的关系 4.总结 二.Cookie与Session详解 1.Cookie 2.Session 3.token 4.总结 三.Django操作Cookie 1.设置Cookie 2.获取Cookie 3.设置超时时间 4.注销Cookie 5.登录功能实…...

Vue批量全局处理undefined和null转为““ 空字符串

我们在处理后台返回的信息&#xff0c;有的时候返回的是undefined或者null&#xff0c;这种字符串容易引起用户的误解&#xff0c;所以需要我们把这些字符串处理一下。 如果每个页面都单独处理&#xff0c;那么页面会很冗余&#xff0c;并且后期如果有修改容易遗漏&#xff0c…...

【2023年APMCM亚太杯C题】完整数据与解题思路

2023年亚太杯C题 数据下载与搜集重点数据其余数据第一问第二问第三问第四问第五问第六问 数据与思路获取 数据下载与搜集 该题并没有提供数据集&#xff0c;对所需数据进行收集整理是对题目进行求解的基础。在本题中&#xff0c;主要需要以下数据&#xff1a;新能源汽车历史销…...

嵌入式单片机方向和Linux驱动开发方向哪个发展前景好?

嵌入式单片机方向和Linux驱动开发方向哪个发展前景好&#xff1f; 在某些平台上看到很多人鼓吹嵌入式Linux开发比单片机开发要好&#xff0c;让所有人都去做嵌入式Linux开发。说这种话的人大多数是嵌入式Linux的培训机构&#xff0c;或者是一开始就以嵌入式Linux入门的那一批人…...

如何搭建Zblog网站并通过内网穿透将个人博客发布到公网

文章目录 1. 前言2. Z-blog网站搭建2.1 XAMPP环境设置2.2 Z-blog安装2.3 Z-blog网页测试2.4 Cpolar安装和注册 3. 本地网页发布3.1. Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 想要成为一个合格的技术宅或程序员&#xff0c;自己搭建网站制作网页是绕…...

2:kotlin集合(Collections)

集合有助于数据分组&#xff0c;方便后续操作 集合类型说明Lists有序的可重复的集合Sets无序的不可重复的集合Maps键值对映射集合&#xff0c;键唯一&#xff0c;且一个键只能映射到一个值 每个集合类型都可以是可变的或者只读的 List List按照添加的顺序存储内容&#xff…...

小诺2.0开源版工程启动

小诺是一款开源的前后端开发框架&#xff0c;同若依、SpringBladex一样可作为私活、外包脚手架。 开源地址&#xff1a;Snowy: 最新&#xff1a;&#x1f496;国内首个国密前后分离快速开发平台&#x1f496;&#xff0c;采用Vue3AntDesignVue3 ViteSpringBootMpHuToolSaToke…...

idea手动导入maven包

当maven仓库中没有包时&#xff0c;我们需要手动导入jar到maven项目中 1.这里的maven设置成你自己安装的maven 2.查看pom.xml文件中maven&#xff0c;以下面为例 <dependency><groupId>com.jdd.pay</groupId><artifactId>mapi-sdk-v3</artifactId&…...

2、单片机及开发板介绍

单片机介绍 单片机&#xff0c;英文Micro Controller Unit,简称&#xff1a;MCU 内部集成&#xff1a;CPU、RAM(随机存储器)、ROM&#xff08;只读存储器&#xff09;、定时器、中断系统、通讯接口等 作用&#xff1a;信息采集&#xff08;传感器&#xff09;、处理&#xff0…...

Leetcode 第 372 场周赛题解

Leetcode 第 372 场周赛题解 Leetcode 第 372 场周赛题解题目1&#xff1a;2937. 使三个字符串相等思路代码复杂度分析 题目2&#xff1a;2938. 区分黑球与白球思路代码复杂度分析 题目3&#xff1a;2939. 最大异或乘积思路代码复杂度分析 题目4&#xff1a;2940. 找到 Alice 和…...

mysql查询统计最近12个月的数据

项目场景&#xff1a; mysql查询统计最近12个月的数据&#xff0c;按每个月纵向展示&#xff0c;效果图 sql语句 注意&#xff1a;count( v.uuid ) 这里的是被统计那张表的id SELECT m.month,count( v.uuid ) AS total FROM (SELECT DATE_FORMAT(( CURDATE()), %Y-%m ) AS mon…...

14.Python 模块

目录 1. 使用模块2. 使用包3. 常用模块3.1 日期和时间3.2 伪随机数3.3 摘要算法3.4 JSON 处理3.5 图像处理 模块是Python用来组织代码的一种方法&#xff0c;包是Python用来组织模块的一种方法。 常用基本语法如下&#xff1a; Windows 按住winR 输入 cmd&#xff0c;Mac 打开…...

三十分钟学会Linux的基本操作

GNU/Linux GNU项目是由Richard Stallman发起的自由软件运动&#xff0c;旨在创建一个完全自由的操作系统。虽然GNU项目已经开发了大量的系统组件和工具&#xff0c;但它一直缺少一个完整的操作系统内核。在这时Linus Torvalds开发了Linux内核&#xff0c;并将其发布为自由软件…...

1688商品详情数据接口(1688.item_get)

1688商品详情数据接口是一种程序化的接口&#xff0c;通过这个接口&#xff0c;商家或开发者可以使用自己的编程技能&#xff0c;对1688平台上的商品信息进行查询、获取和更新。这个接口允许商家根据自身的需求&#xff0c;获取商品的详细信息&#xff0c;例如价格、库存、描述…...

SA实战 ·《SpringCloud Alibaba实战》第14章-服务网关加餐:SpringCloud Gateway核心技术

大家好,我是冰河~~ 一不小心《SpringCloud Alibaba实战》专栏都更新到第14章了,再不上车就跟不上了,小伙伴们快跟上啊! 在《SpringCloud Alibaba实战》专栏前面的文章中,我们实现了用户微服务、商品微服务和订单微服务之间的远程调用,并且实现了服务调用的负载均衡。也基…...

设计师不能忽视的几个宝藏图标设计工具

在这个快速变化的时代&#xff0c;设计师对创新和实用工具的需求越来越大。这就要求我们及时跟上潮流&#xff0c;不断探索和尝试最新、最有价值的图标设计工具。只有这样&#xff0c;我们才能在竞争激烈的设计市场中脱颖而出。以下是我们精心挑选的2024年值得一试的图标设计工…...

设计模式-行为型模式-模板方法模式

一、什么是模板模式 模板方法模式&#xff08;Template Method Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一个算法骨架&#xff0c;允许子类在不改变算法整体结构的情况下重新定义算法的某些步骤。 主要组成部分&#xff1a; 1、模板方法&#xff08;Templ…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...