作为系列文章的开始,本文整理了 Rust 的类型系统。
所有内容参考 https://doc.rust-lang.org/reference/types.html,但分类标准略有不同。增加了部分注释。
基本数据类型
类型名称 |
大小 |
说明 |
bool |
1 |
只能为逻辑值 true 或 false |
i8 /i16 /i32 /i64 |
1/2/4/8 |
8/16/32/64 位有符号整数,采用补码表示法 |
u8 /u16 /u32 /u64 |
1/2/4/8 |
8/16/32/64 位无符号整数,采用补码表示法 |
isize /usize |
平台相关 |
有/无符号整数,大小与体系结构规定的指针相等,至少为16位1 |
f32 /f64 |
4/8 |
IEEE-754 单/双精度浮点数 |
char |
4 |
Unicode 标量值,范围在 U+0 ~ U+D7FF 和 U+E000 ~ U+10FFFF(含两端)内,以 32 位无符号整数形式表示 |
str |
动态 (DST) |
采用 UTF-8 编码的合法字符串,以 [u8] 数组形式表示2 |
! (never) |
- |
发散函数的返回值类型,不能定义实例,没有有效取值 |
积类型
元组 (tuple)
由任意多个同种或异种类型的元素捆绑组成的类型,根据用户指定的元组成员顺序,每个元素与相应的顺序号 0、1、2……绑定。
支持空元组 ()
,空元组又称为单元类型 (unit type)。
注意 Rust 并不保证元组的物理存储顺序,有可能与元素的顺序号不同。
结构体 (struct)
由任意多个同种或异种类型的元素捆绑组成的类型,每个元素各自与一个名称(结构体成员)绑定。支持空结构体 StructType {}
。
与元组相似,Rust 不保证结构体成员的物理存储顺序。
数组 (array)
由固定个数的同种类型的元素按顺序排列组成的类型。
数组的所有成员在内存中总是按顺序紧接着存储,对于数组类型 [T; N]
,总是可以在数组起始位置上增加偏移量 n * size_of::<T>
来找到第 n 个元素。
切片 (slice)
切片类型是动态大小类型(DST),表示一组同种元素组成的序列的「视图」。通常与指针类型结合使用。
和类型
枚举 (enum)
与 C 语言的 union
类似,但是各种可能的类型通过标记(枚举值)区分。
每个成员可以是结构体、元组或单元类型。如果所有成员均为单元类型,则与 C 语言的枚举等同。
由于 Rust 的枚举可通过标记区分到底是哪一种成员的值,因此访问枚举成员是安全的。
联合 (union)
与 C 语言的 union
相同,可在多种类型的合法值集合的并集中取值。
编译器无法通过类型系统确定一个 union 具体取了哪种成员的值,因此通过 union 成员取值是不安全的。
函数类型
函数 (function)
通过 fn
关键字定义的函数的类型。每个通过 fn
定义的函数都具有唯一对应的函数类型3。
注意,函数的名称和泛型参数也都是函数类型的一部分。函数类型可以隐式转换为函数指针类型,此时会舍去函数名称部分。
两个不同名但参数列表和返回值类型都相同的函数,属于不同类型,但可以隐式转换为相同的函数指针类型。
闭包 (closure)
通过闭包表达式定义的闭包所具有的匿名类型,无法在源代码中显式写出。类似于带有捕获变量、定义了调用方法的结构体。
指针类型
引用 (reference)
通过 &
或 &mut
标记(分别表示不可以/可以通过该引用修改被引用的值)指定的变量引用。
裸指针 (raw pointer)
通过 *const
或 *mut
标记(分别表示不可以/可以通过该指针修改指向的值)指定的裸指针。解引用裸指针是不安全操作。
函数指针 (function pointer)
通过参数列表、返回值类型和调用约定指定的函数指针。
当且仅当指定了使用 C 语言调用约定(extern "C"
或 extern "cdecl"
)时,可以使用可变参数。
特征类型
特征对象 (trait object)
通过 dyn
关键字加一个或多个特征约束(其中至多有一个非自动特征 (non-auto trait))以及可选生命周期约束指定的类型。特征对象自动实现了所有在约束中指定的特征。
特征对象的值可以是任何满足全部约束的类型的值,因此特征对象类型是动态大小类型,通常结合指针类型使用。此时特征对象指针是一个胖指针 (fat pointer),包括一个指向实际数据的指针和相应特征的虚函数表,可以实现后期绑定。
匿名参数类型/抽象返回类型 (impl trait)
通过 impl
关键字加一个或多个特征约束指定的匿名类型,可以出现在函数参数或函数返回值处。
出现在函数参数时,语义与泛型参数类似,但调用者无法使用 Turbofish 语法强制指定实际的参数类型。
出现在返回值时,表示一个抽象返回类型(可能由于实际的返回类型名称过长,或者希望通过返回类型提示相应的接口、但不希望调用者关心具体实现)。函数实现需要给出函数的实际返回值,这个实际返回值的类型将是抽象返回类型对应的实际返回类型。