
1 Rust变量与类型
常量与不可变
const 编译期常量
.
let 运行时常量,默认不可变,编译器约束可变操作(改变变量栈内存与堆内存的操作)无法通过编译。
.
let mut 变量可编译通过可变操作。
默认let 虽然不可变,但是将变量“所有权”赋予另外的可变变量则可变了。想要其他编程语言中“普通的变量”在rust中应该是let mut。
编译期常量不能通过编译器动态推断类型,所以rust必须让我们对const常量 标记类型。
重复声明=遮蔽
在变量的作用域中声明同名变量,之前的变量并不会被覆盖或者释放,只是失去了这个标识符,本身可以通过引用之类的方式继续访问。
数据类型
值之所有能被同一套处理方法处理,是因为有相同的结构。
rust内置了对几种数据的存储、识别、处理方法,所以这些类型的值的内部结构已经无法再分,所以内置了,他们都有已知的内存大小和数据标识,可以直接识别,存储。
而复合类型,由rust代码定义,只有当这段定义代码执行之后,rust才能根据定义创造出对应的数据,分配对应的内存结构。
标量
四种基本的标量类型:整型、浮点型、布尔类型和字符类型。
.
按助记来记,就是:数学上的两种,逻辑运算的一种,字符编码一种。
非常简单的基本数据类型,但是根据所存储内存的大小,又有细分类型。
| 长度 | 有符号 | 无符号 | 字面量行为 |
|---|---|---|---|
| 8-bit | i8 | u8 | 有类型自动推导 |
| 16-bit | i16 | u16 | 有类型自动推导 |
| 32-bit | i32 | u32 | 无类型则默认 |
| 64-bit | i64 | u64 | 有类型自动推导 |
| 128-bit | i128 | u128 | 有类型自动推导 |
| 架构相关 | isize | usize | 有类型自动推导 |
在 debug 模式下,Rust 会加入整型溢出的检查,并在发生这种情况时让程序在运行时panic,也就是错误退出。但在release模式下会允许溢出回绕。
.
rust提供了显式处理溢出的方法,标准库中有几种函数可以做到。
| 数字字面值 | 例子 |
|---|---|
| Decimal(十进制) | 98_222 |
| Hex(十六进制) | 0xff |
| Octal(八进制) | 0o77 |
| Binary(二进制) | 0b1111_0000 |
Byte(字节ASCII字面值,仅限 u8) | b'A' |
浮点数分为f32 和 f64,分别占 32 位和 64 位。默认类型是 f64,所有的浮点型都是有符号的。
在进行数值运算的时候,其他编程语言基本上都从c语言中吸收了“隐式转换”来让不同类型的数据能进行运算的思路。但rust只允许同类型的数据进行运算,我们只能手动转换类型然后进行运算。
这避免了隐式转换带来的各种问题!
可以通过对象直接调用对象所属类型的静态方法进行转换。
Target::from(value),Target::try_from(value) 通过目标类型的实现
.
value.into() value.try_into() 通过编译器类型推导转换成from形式
value as Target 底层 /unsafe 场景,不推荐
Rust 的 char 类型大小为 4 个字节,并表示一个 Unicode 标量值。
字符串字面值和静态常量是程序运行所需要的数据,这些数据固化在程序代码中,所以在内存中我们不希望遗忘这些信息(否则要重新从磁盘加载),这些数据既然存在,那么不再希望为其分配内存,所以当用到这些值,都是静态只读引用。
.
而基本数据类型因为内存开销非常小,每次从函数定义中分配内存到栈上,也能提供运行效率。
复合类型
这个“快速”是非常重要的。因为后面还有不快速的“结构体、枚举”之类的。
.
内置两种复合类型,元组,数组。
.
rust原生提供这复合类型的“快速复合”语法,通过“快速复合”语法我们能快速声明一个复合类型。
比如声明一个“拥有三个元素,第一个元素是i32,第二个元素是f64,第三个元素是bool的元组”类型。
let x:(i32,f64,bool) = (12,30.0,true);
这里的小括号就是元组的”快速复合”语法,同时也是构造值的语法。
方括号是语法关键,在声明的时候使用分号分隔类型与数组长度的参数。在构造值的时候可以使用逗号,或者也可以使用分号
let arr:[i32;5] = [1;5];
这样构造的值是1重复5次。
数组和元组类似,但是数组不允许元素的类型不同。数组中的每个元素都必须具有相同类型。Rust 的数组长度是固定的。
let arr:[i32;5] = [1,2,3,4,5];
-
可以通过小括号将元组中的元素拆出来,通过模式匹配。就像构建元组的反操作一样。
let (x,y,z) = (123,456,789);
甚至可以反引用解构:for (i,&y) in 1..5.iter().enumerate() -
或者我们可以直接通过
.访问元组的下标元素
let x = (123,456,789).0;
另外有一种特殊的元组,空元素,只有一个值,叫作Unit单元,这种值以及其对应的类型都写作 (),表示空值或空的返回类型。如果一个表达式没有返回任何其他值,它就会隐式返回单元值。
Debug 模式 → 一定会 panic
Release 模式 → 默认仍然会检查、仍然会 panic!除非手动关闭边界检查。
.
官方推荐使用迭代而不是直接使用索引访问,如果要使用索引最好用get函数访问而非访问修饰符。
定长数组是编译器固定长度的数组,就是我们这里说的数组。切片是不定长的,是一种胖引用,可以包含任意长度。Vec是一种变长数组。
下一节 1.1 rust所有权机制
