Skip to main content
rust 学习

1 Rust变量与类型

•2 min•237 words

常量与不可变

编译期常量,运行时常量,普通变量

const 编译期常量
.
let 运行时常量,默认不可变,编译器约束可变操作(改变变量栈内存与堆内存的操作)无法通过编译。
.
let mut 变量可编译通过可变操作。

默认let 虽然不可变,但是将变量“所有权”赋予另外的可变变量则可变了。想要其他编程语言中“普通的变量”在rust中应该是let mut。

编译期常量不能通过编译器动态推断类型,所以rust必须让我们对const常量 标记类型。

重复声明=遮蔽

被遮蔽的变量不会失效

在变量的作用域中声明同名变量,之前的变量并不会被覆盖或者释放,只是失去了这个标识符,本身可以通过引用之类的方式继续访问。

数据类型

类型是一类值的统一容器,这些值被归为同类的原因,他们可以应用于同一套处理方法

值之所有能被同一套处理方法处理,是因为有相同的结构。

rust内置了对几种数据的存储、识别、处理方法,所以这些类型的值的内部结构已经无法再分,所以内置了,他们都有已知的内存大小和数据标识,可以直接识别,存储。

而复合类型,由rust代码定义,只有当这段定义代码执行之后,rust才能根据定义创造出对应的数据,分配对应的内存结构。

标量

Rust的标量类型

四种基本的标量类型:整型、浮点型、布尔类型和字符类型。
.
按助记来记,就是:数学上的两种,逻辑运算的一种,字符编码一种。

非常简单的基本数据类型,但是根据所存储内存的大小,又有细分类型。

长度有符号无符号字面量行为
8-biti8u8有类型自动推导
16-biti16u16有类型自动推导
32-biti32u32无类型则默认
64-biti64u64有类型自动推导
128-biti128u128有类型自动推导
架构相关isizeusize有类型自动推导
整型溢出 默认行为

在 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];

Summary
  1. 可以通过小括号将元组中的元素拆出来,通过模式匹配。就像构建元组的反操作一样。
    let (x,y,z) = (123,456,789);
    甚至可以反引用解构:for (i,&y) in 1..5.iter().enumerate()

  2. 或者我们可以直接通过.访问元组的下标元素
    let x = (123,456,789).0;

另外有一种特殊的元组,空元素,只有一个值,叫作Unit单元,这种值以及其对应的类型都写作 (),表示空值或空的返回类型。如果一个表达式没有返回任何其他值,它就会隐式返回单元值。

数组访问越界

Debug 模式 → 一定会 panic
Release 模式 → 默认仍然会检查、仍然会 panic!除非手动关闭边界检查。
.
官方推荐使用迭代而不是直接使用索引访问,如果要使用索引最好用get函数访问而非访问修饰符。

定长数组与切片以及Vec类型不同

定长数组是编译器固定长度的数组,就是我们这里说的数组。切片是不定长的,是一种胖引用,可以包含任意长度。Vec是一种变长数组。

下一节 1.1 rust所有权机制