【Rust学习记录】3. 通用编程概念
变量,可变性,隐藏,常量
这部分的内容基本都在前面了解过了,大致就是一下内容
变量与可变性
Rust 默认变量是不可变的,需要可变的话需要加上 mut
关键字。
隐藏
但没有 mut
的变量也可以进行修改,那就是 shadow 机制(翻译为“隐藏”,其实我不太能接受,因为“隐藏”这个词汇常常涉及到安全隐患,但在 Rust 中并非如此)。我们可以通过再 let
一个同名变量,来修改。
1 | let x = 4; |
这是可以编译通过的。
通过 shadow 来修改变量,和定义 mut
来修改变量的区别是:shadow 可以修改变量的类型,就和我们猜数游戏的 guess
一样,一开始存字符串,后面存 i32,但不同类型的变量在相互赋值时,是会报错的。
常量
和变量不同的是,常量需要显式声明类型,并且必须用常量表达式来赋值。常量使用 const
关键字声明,而不是 let
。
1 | fn main() { |
值得一提的是,Rust 支持在数字中间加个下划线提高可读性
数据类型
Rust 本质还是一个静态语言,需要显示的给出变量的具体类型。不过有不少情况,编译器能根据实际情况推导出我们的实际类型罢了,但像 guess
需要作类型转换的时候,还是需要给出具体的类型,上面的常量定义的时候,也需要显示给出变量类型。
定义变量类型的方式也就是上面那样,用冒号加类型
如果要加的时候没有加类型,就会报 cannot infer type for xxxx
意思就是编译器推导不出来类型了,要你给。
标量类型
基本的类型,整型,浮点型,布尔类型,字符型
整型
根据长度命名,有符号为 i8
, i16
, i32
, i64
,无符号为 u8
, u16
, u32
, u64
比较特殊的是isize
, usize
,这两个的长度根据本地环境而定,如果运行的环境是32位系统就是32位,64位系统就是64位。感觉挺牛的。
浮点型
只有两种,f32
和f64
,值得一提的时候,Rust 默认会将浮点型推导为 f64
,表述方法是 IEEE-754
布尔型
没什么好说的,:bool
字符型
Rust 用的字符型是用 Unicode 的,而不是 ASCLL,占4个字节;定义和C++一样,字符是单引号,字符串是双引号。
但 Unicode 实际并没有“字符”的概念,所以有点奇怪,书上说是后面会解释
复合类型
基础提供的有 tuple
和 array
定义方面和 python 像,tuple
用圆括号定义,array
用方括号定义。
底层方面和 c++ 差不多,array 在栈上分配一整片内存,而 tupple 是在堆上分配不一定连续的内存
但两者都是长度不可变的,如果要数组长度可变,可以使用动态数组 vector
,这里书上没介绍
tuple 的基本操作:
1 | let a:(i32, u32, f32) = (1, 2, 3.0); // 指定类型 |
值得一提的是,这里的模式匹配赋值需要带括号 let (x, y, z) = b;
array 的基本操作:
1 | let a:[i32; 5] = [3, 3, 3, 3, 3] // 指定类型 |
Rust 在每次执行数组下标访问的时候,都会作边界检查,如果访问越界的话会抛出异常,然后终止程序运行。而不像 c++ 会自作主张的运行,造成某些难以察觉的 bug
函数
函数怎么定义的,在前面也讲过了,就是 fn
,其中传入参数的类型,返回值的类型必须显示定义。
1 | // 指定数据类型,返回值类型 |
语句和表达式
在Rust里有两个基本的概念,
- 语句:执行操作,但不返回值
- 表达式:进行计算,返回计算值
let
操作就是一个语句,所以不能进行
1 | let a = (let b = 1); |
当然也不能写 a = b = 1
这样的语句,因为这些在Rust都是语句,不返回值,不能赋值
而 let b = 1
中的 1 ,本身就是表达式,返回1, 函数也是个表达式,返回函数的返回值,而我们写的花括号{}
,本质上也是个表达式,也能返回值,所以上面的语句我们可以写成
1 | let a = { |
花括号就是一个表达式吗,它执行一系列的操作,并返回一个返回值,b+1
也是一个表达式,返回 b+1
的值,值得一提的是,b + 1
后面没加分号,如果加了分号,那它就是语句,不是表达式,不会返回值了,这时候编译也会报错。这应该也是之前看到的,Rust 返回值的办法,默认不需要用 return
语句,而是采用表达式的办法。
Rust 默认函数的返回值就是最后一个表达式,但可以使用 return 关键字提前返回
如果函数没有返回值,函数会返回一个空元组;没有指定返回类型,也会默认类型是空元组
若类型不匹配,自然就会编译报错
注释
没什么好说的 //
控制流
if-else表达式
语法和 c++ 几乎一样,但不需要打圆括号,好评
1 | fn main() { |
值得一提的是,rust 里的 if
表达式只接受 bool
值,而不会像其他一些语言一样,把不等于 0 的值自动当成 bool
值。也就是在上例不能写成 if num{};
同样,这里if else
是表达式,而不是语句,也就是说,它可以返回值,所以我们也能用 if 表达式给变量赋值。但同时需要注意类型问题,两个分支不同类型的赋值,还是会编译报错
1 | fn main() { |
循环
loop循环
前面已经介绍过 loop
循环表达式了,就是相当于 while true
,值得一提的是,表达式,对,loop
也是一个表达式,可以通过 break
返回值。没错,在 Rust 里 break 居然可以返回值!
1 | fn main() { |
while 循环
很常规的循环,但while
就不能用来返回值了,break
不能带数值。
1 | fn main() { |
for 循环
Rust 里的 for
循环和python差不多,是通过迭代器来进行循环的,这在遍历像数组一样的结构时比较舒服,主要是1. 不会有越界的危险 2. 不需要每次执行过后作一次条件判断。
1 | fn main() { |
0..4
确实有点惊到我,抽象程度还挺高。
至此,第三章基本概念结束!这章里面,虽然基本知识很多,但也有不少Rust独特之处,挺惊喜的,可以看到很多地方有些和 python 的相似程度,在保证和 c++ 差不多效率的情况下,在一些语法简洁方面向python看齐(例如自动推导类型),处处都体现着,这确实是一个很现代化的语言。
- 标题: 【Rust学习记录】3. 通用编程概念
- 作者: TwoSix
- 创建于 : 2023-03-25 19:48:36
- 更新于 : 2024-07-04 23:52:28
- 链接: https://twosix.page/2023/03/25/【Rust学习记录】3-通用编程概念/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。