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

Rust 学习笔记 - 变量声明与使用

前言

任何一门编程语言几乎都脱离不了:变量、基本类型、函数、注释、循环、条件判断,这是一门编程语言的语法基础,只有当掌握这些基础语法及概念才能更好的学习 Rust。

变量介绍

Rust 是一种强类型语言,但在声明变量时,不总是需要显式声明类型,这是因为 Rust 的编译器有类型推断系统。当声明一个变量而没有指定类型时,Rust 编译器会根据变量的初始值自动推断出它的类型。

在强类型语言中,每个变量和常量都必须有一个明确的类型,而且类型在编译时就已经确定。Rust 编译器非常严格,不允许不同类型的数据隐式转换。如果需要将一个类型转换为另一个类型,必须使用明确的类型转换方法。这一特性使得 Rust 在编译时能够提供类型检查,有助于避免许多常见的运行时错误。

不可变变量 (Immutable)

与其他编程语言(如:Java、Python、JS)不同,默认情况下 Rust 中的变量是不可变的 (神奇,变量不可变🤔)。

这一特性意味着变量一旦被赋值后,在变量的整个生命周期内它的值就不能被改变,尝试修改一个不可变变量的值会导致编译时错误。

示例:

let x = 5;
x = 6; // 这会导致编译错误,因为 x 是不可变的

可变变量 (Mutable)

  • 通过使用 mut 关键字,可以声明一个可变的变量,这样的变量允许其值在后续被修改。
  • 但需要注意,rust 作为强类型语言,修改变量时不允许赋值其他类型的值

示例:

let mut x = 5;
x = 6; // 这是允许的,因为 x 是可变的// error[E0308]: mismatched types
x = 3.1415926; // 3.1415926 是浮点数,x 声明时是整形

变量遮蔽(Shadowing)

变量遮蔽是 Rust 中的一个特性,有些文档或教程将 Shadowing 称为:隐藏重影,它允许在相同作用域中,使用相同的名称声明一个新变量。这个新声明的变量“遮蔽”了先前声明的同名变量。更准确地说,当新变量被引入时,它会使得与之同名的先前变量不再可见,直到新变量离开作用域前,无法访问被遮蔽的变量。这与变量重新赋值不同,因为它实际上是在创建一个全新的变量。

遮蔽的好处是可以重新使用更有意义或适用于当前上下文的变量名,遮蔽通常用于转换值的类型或给变量一个新值,而这样做并不影响原来变量的不可变性。

示例1:

let x = 5;
let x = x + 1; // 遮蔽前一个 x 变量
let x = "现在 x 是一个字符串"; // 再次遮蔽,改变了值的类型

示例2:

fn main() {let x = 5;let x = x + 1;{// 在使用花括号创建的内部作用域内,变量 `x` 被遮蔽let x = x * 2;println!("x 在当前作用域的值是: {x}"); // 12}// 当作用域结束后,内部 shadowing 的作用域也结束了,`x` 又返回到 `6`println!("x 在当前作用域的值是: {x}"); // 6
}

常量 (Constants)

  • 常量使用 const 关键字声明,并且它们总是不可变的。
  • 常量必须在声明时就赋值,而且它们的类型必须显式声明。
  • 常量名应该全部大写,否则会报警告。

示例:

const MAX_POINT: u32 = 100_000;

不可变变量 与 常量的区别

在 Rust 中,虽然不可变变量和常量都不能在声明后被修改,但它们之间存在几个主要区别:

类型标注

  • 声明常量时,必须显式给出类型标注
  • 不可变变量通常可以依赖 Rust 的类型推断,类型标注是可选的。

示例:

// ok!
let x = 1000;
// error: missing type for `const` item
const CONST_VAL = 1000; 

值的赋予时机

  • 常量在编译时被赋值,且必须是一个恒定的表达式,不能是运行时的结果。
  • 不可变变量可以在运行时被初始化,其中的值可以是在运行时才能确定的表达式的结果。

示例1:

fn get_val() -> i32 {1000
}fn main() {// ok!let x = get_val(); // const 不能接收运行时的结果// error[E0015]: cannot call non-const fn `get_val` in constantsconst CONST_VAL: i32 = get_val(); 
}

示例2:

fn main() {// let 允许先声明,后赋值let x;x = 1000; // error: free constant item without bodyconst CONST_VAL: i32; // error[E0070]: invalid left-hand side of assignmentCONST_VAL = 1000;
}

变量遮蔽

  • 不可变变量可以通过变量遮蔽进行重新赋值
  • 常量无法进行变量遮蔽,相同常量名重复定义时会报错

示例:

    let x = 1000;// ok!let x = "str";const CONST_VAL: i32 = 1000;//  // error[E0428]: the name `CONST_VAL` is defined multiple timesconst CONST_VAL: &str = "str";

作用域

  • let 关键字用于在局部作用域中声明变量,如函数或代码块内部,而不能用于全局作用域。
  • const 关键字可以用于全局作用域中声明常量,也可以在局部作用域中使用。

示例:

const GLOBAL_CONST: i32 = 10; // 全局常量,可以在整个程序中访问// error: expected item, found keyword `let`
// let x = 1000; // 不允许声明全局变量
fn main() {let local_var = 5; // 局部变量,只能在 main 函数内访问println!("常量: {}", GLOBAL_CONST);println!("局部变量: {}", local_var);
}fn another_function() {// local_var 在这里是不可见的,因为它不在作用域内// GLOBAL_CONST 仍然是可见的println!("同一个常量: {}", GLOBAL_CONST);
}

结语

本文深入介绍了 Rust 中的变量声明,特别是它独有的不可变变量变量遮蔽特性。相较于其它编程语言,这些概念初看可能会给变量操作带来复杂性。然而,随着使用的深入,这些概念将变得清晰明了,你将发现它们实际上是 Rust 强大功能和安全性的体现,而且并不复杂。

相关文章:

  • 用C语言列出Linux或Unix上的网络适配器
  • 5.9 BCC工具之nodejs_http_server.py简介
  • [前端开发] 常见的 HTML CSS JavaScript 事件
  • aiofiles:解锁异步文件操作的神器
  • Unity类银河恶魔城学习记录7-6 P72 Bouncy sword源代码
  • LLM之LangChain(七)| 使用LangChain,LangSmith实现Prompt工程ToT
  • 树与二叉树---数据结构
  • bat脚本 创建计划任务 一分钟设置ntp同步周期为60s
  • Gin框架: 快速搭建起一个Web应用环境及处理不同类型的响应
  • wordpress外贸成品网站模板
  • 二叉树相关OJ题
  • Python编程中的异常处理
  • 利用Excel模拟投币试验
  • 简单试验:用Excel进行爬虫
  • 双活工作关于nacos注册中心的数据迁移
  • 【css3】浏览器内核及其兼容性
  • android 一些 utils
  • JavaScript实现分页效果
  • Java面向对象及其三大特征
  • Linux链接文件
  • MySQL QA
  • MySQL用户中的%到底包不包括localhost?
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • vue学习系列(二)vue-cli
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 首页查询功能的一次实现过程
  • 数组大概知多少
  • 再次简单明了总结flex布局,一看就懂...
  • 阿里云移动端播放器高级功能介绍
  • #define
  • #NOIP 2014# day.1 T2 联合权值
  • (003)SlickEdit Unity的补全
  • (2022 CVPR) Unbiased Teacher v2
  • (4)logging(日志模块)
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (分类)KNN算法- 参数调优
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (简单) HDU 2612 Find a way,BFS。
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (转)memcache、redis缓存
  • (转)创业家杂志:UCWEB天使第一步
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • .Net 中Partitioner static与dynamic的性能对比
  • .NET 中创建支持集合初始化器的类型
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • .net经典笔试题
  • @RequestMapping处理请求异常
  • [2544]最短路 (两种算法)(HDU)