rust类型

内置类型列表:

  • 原生类型(primitive types):
    • 布尔型(Boolean) --- true 或 false
    • 数字类(Numeric) --- 整型(integer) 和 浮点型(float)
    • 文本类(Textual) --- 字符型(char) 和 字符串切片(str)
    • never类型 --- ! 没有值的类型
  • 序列类型(sequence types):
    • 元组(Tuple)
    • 数组(Array)
    • 切片(Slice)
  • 用户自定义类型(user-defined types):
    • 结构体(Struct)
    • 枚举(Enum)
    • 联合体(Union)
  • 函数类型(function types):
    • 函数(Functions)
    • 闭包(Closures)
  • 指针类型(pointer types):
    • 引用(References)
    • 裸指针(Raw pointers)
    • 函数指针(Function pointers)
  • trait类型(Trait types):
    • trait对象(Trait objects)
    • 实现trait(Impl trait)

一、布尔类型

bool

布尔类型的大小为1个字节。

二、数字类型

1.整数

长度 有符号类型 无符号类型
8位 i8 u8
16位 i16 u16
32位 i32 u32
64位 i64 u64
128位 i128 u128
视运行的cpu而定 isize usize

isize 和 usize 类型取决于程序运行的CPU宽度: 若CPU是32位的,则这两个类型是32位的,若CPU是64位,那么它们则是64位。

2.浮点数

f32 32位

f64 64位

默认浮点类型是f64,在现代的CPU中它的速度与f32几乎相同,但精度更高。

三、文本类型

1.字符类型

char

4个字节,值是字符的Unicode码。取值范围为0x0000~0xD7FF0xE000~0x10FFFF

2.字符串

str

str类型的值的表示方法与 [u8] 相同。但是,Rust标准库对 str 做了额外的限定:str的方法会假定数据是有效的UTF-8。

由于 str 是一个动态大小类型,所以只能使用它的指针类型,比如&str。

四、never类型

用!表示

never类型是一个没有值的类型。一些根本无返回值的情况,比如崩溃、break、continue等行为

!类型的表达式可以自动转换为任何其他类型。

在函数从不返回的时候充当返回值。例如:

fn bar() -> ! {
     // --snip--
}

这读 "函数bar从不返回",而从不返回的函数被称为 发散函数(diverging functions)。不能创建 ! 类型的值,所以bar也不可能返回值。

不过一个不能创建值的类型有什么用呢?

let guess: u32 = match guess.trim().parse() {
     Ok(num) => num,
     Err(_) => panic!(),
};

match要求所有分支必须是相同类型的,为什么这里允许一个分支返回u32而另一个分支却是panic!()呢?因为panic!()的类型是 !,可以自动转换成u32。

五、元组

由多个不同类型组合成一个类型

TupleType :
( )
| ( ( Type , )+ Type? )

元组类型的语法规则为一对圆括号封闭的逗号分割的类型有序列表。一元元组的元素类型后面需要有一个逗号。

元组类型的元素也叫字段。

字段数是类型列表的长度。字段的数量决定元组的元数。有n个字段的元组叫做n元元组。例如,有两个字段的元组就是二元元组。

元组有着固定的长度。一旦定义,就不能再增长或缩小。

元组的字段用它在列表中的位置序号来索引。第一个字段索引为0。第二个字段索引为1。然后以此类推。

不带元素的元组类型(),称为单元类型(unit type)。它的值称为单元值。

元组类型的值是使用元组表达式来构造的。如果一个表达式没有其他有意义的值,那么将返回单元值。

元组类型的示例:

()
(f64, f64)
(String, i32)
(i32, String) 
(i32, f64, Vec<String>, Option<bool>)

六、数组

ArrayType :
[ Type ; Expression ]

数组是N个类型为T的元素组成的固定长度的序列,

数组类型写为 [T; N]。

长度是一个计算结果为 usize 的常量表达式。

示例:

let array: [i32; 3] = [1, 2, 3];// 一个栈分配的数组

数组的所有元素总是初始化过的,使用Rust中的安全方法或操作符来访问数组时总是会先做越界检查。

七、切片(Slice)

切片就是数组片段

SliceType :
[ Type ]

切片是一种动态大小类型。切片的大小是运行时才可知的,并不是数组那种编译时就必须确定的。

切片类型写为 [T]。但要使用切片类型时,必须使用它的指针类型,例如:

&[T],共享切片('shared slice'),常直接称为切片(slice),它不拥有它指向的数据,只是借用。

&mut [T],可变切片('mutable slice'),可变借用它指向的数据。

示例:

let slice: &[i32] = &boxed_array[..];// 数组上的切片

切片的所有元素总是初始化过的,使用Rust中的安全方法或操作符来访问切片时总是会做越界检查。

八、结构体

结构体是一种自定义的数据类型,它可以将多个不同类型组合在一起形成一个新的类型。这些其他类型称为结构体类型的字段

结构体的实例可以用结构体表达式来构造。

结构体的字段可以由可见性修饰符限定,以允许从模块之外来访问结构体中的数据。

元组结构体类型与结构体类型类似,只是字段是匿名的。

单元结构体类型类似于结构体类型,只是它没有字段。

结构体与元组的区别是结构体的每个字段和其本身都有一个名字,这样访问字段的时候就不用记住下标了。

九、枚举

枚举是一种自定义的数据类型,它可以表示多个可能的值。

十、联合体

联合体类型是一种类似C语言里的union的类型,具体的类型名称由联合体项的名称表示。

声明联合体和声明结构体的语法一样,除了用 union 代替 struct外

十一、函数

当引用函数时,会产生函数类型的值。

例子

fn foo<T>() { }
let x = &mut foo::<i32>;
*x = foo::<u32>; // 错误:类型不匹配

函数类型到函数指针的自动强转

// 这里 `foo_ptr_1` 标注使用了 `fn()` 这个函数指针类型。
let foo_ptr_1: fn() = foo::<i32>;
// ... `foo_ptr_2`  类型自动推断。
let foo_ptr_2 = if want_i32 {
          foo::<i32>
     } else {
         foo::<u32>
};

十二、闭包

闭包类型相当于包含捕获变量的结构体。

比如以下闭包示例:

fn f<F: FnOnce() -> String> (g: F) {
     println!("{}", g());
}
let mut s = String::from("foo");
let t = String::from("bar");
f(|| {
     s += &t;
     s
});
// 打印 "foobar".
生成大致如下所示的闭包类型:
struct Closure<'a> {
     s : String,
     t : &'a String,
}
impl<'a> FnOnce<()> for Closure<'a> {
     type Output = String;
     fn call_once(self) -> String {
         self.s += &*self.t;
         self.s
     }
}
所以调用f相当于:
f(Closure{s: s, t: &t});

十三、引用

Rust中所有的指针都是显式的头等(first-class)值。 它们可以被移动或复制,存储到其他数据结构中,或从函数中返回。

ReferenceType :
   & Lifetime? mut? TypeNoBounds

共享引用(&)

共享引用(&)指向由其他值拥有的内存。不可更改其值。对一个值的共享引用的次数没有限制。

共享引用类型被写为 &type;当需要指定显式的生存期时可写为 &'a type。

可变引用(&mut)

可变引用(&mut)也指向其他值所拥有的内存。可更改其值。对一个值只能有一个可变引用。

可变引用类型被写为 &mut type或 &'a mut type。

十四、裸指针

RawPointerType :
   * ( mut | const ) TypeNoBounds

裸指针是没有安全性保证的指针。

裸指针写为 *const T或 *mut T,例如,*const i32表示指向32-bit有符号整数的裸指针。拷贝或销毁裸指针对任何其他值的生命期都没有影响。对 裸指针的解引用是非安全操作,可以通过重新借用裸指针(&* 或 &mut *)将其转换为引用。

在Rust代码中不鼓励使用裸指针;它们是为了提升与外部代码的互操作性,以及编写对性能要求很高的函数或很底层的函数。

在比较裸指针时,比较的是它们的地址,而不是它们指向的数据。当比较裸指针和动态尺寸类型时,还会比较它们指针上的附加/元数据。

可以直接使用 core::ptr::addr_of! 创建 *const类型的裸指针,通过 core::ptr::addr_of_mut! 创建 *mut类型的裸指针。

十五、函数指针

BareFunctionType :
ForLifetimes? unsafe? (extern Abi?)? fn( FunctionParametersMaybeNamedVariadic? ) -> TypeNoBounds?

函数指针类型指向那些在编译时不必知道名字的函数。它们也可以由函数类型或非捕获闭包经过自动强转而来。

非安全(unsafe)限定符表示类型的值是一个非安全函数,而外部(extern)限定符表示它是一个外部函数。

示例

fn add(x: i32, y: i32) -> i32 {
     x + y
}
let mut x = add(5,7);
type Binop = fn(i32, i32) -> i32;     //Binop为函数指针类型:
let bo: Binop = add;
x = bo(5,7);

十六、trait对象

TraitObjectType :
   dyn? TypeParamBounds
TraitObjectTypeOneBound :
   dyn? TraitBound

trait对象是关键字dyn后跟一组trait约束。

trait对象是动态尺寸类型。像所有的 DST 一样,trait对象常被用在某种类型的指针后面;例如 &dyn SomeTraitBox<dyn SomeTrait>

例子:

trait Printable {
     fn stringify(&self) -> String;
}
impl Printable for i32 {
     fn stringify(&self) -> String { self.to_string() }
}
impl Printable for f32 {
     fn stringify(&self) -> String { self.to_string() }
}
fn print(a: Box<dyn Printable>) {
     println!("{}", a.stringify());
}
fn main() {
     print(Box::new(10));
     print(Box::new(10.0));
}

十七、实现trait

ImplTraitType : impl TypeParamBounds
ImplTraitTypeOneBound : impl TraitBound

impl后跟一组trait约束

trait作为函数参数类型

trait Trait {}
fn foo(arg: impl Trait) {}

trait作为函数返回值类型

fn bar() -> impl Trait {}

十八、自动推断型类型

InferredType : _

编译器自动推断出实际使用类型。它只用于泛型参数中:

let x: Vec<_> = (0..10).collect();
相关推荐
码农飞飞6 小时前
深入理解Rust的模式匹配
开发语言·后端·rust·模式匹配·解构·结构体和枚举
一个小坑货6 小时前
Rust 的简介
开发语言·后端·rust
qq_172805597 小时前
RUST学习教程-安装教程
开发语言·学习·rust·安装
monkey_meng7 小时前
【遵守孤儿规则的External trait pattern】
开发语言·后端·rust
新知图书8 小时前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
fqbqrr12 小时前
2411rust,实现特征
rust
码农飞飞12 小时前
详解Rust枚举类型(enum)的用法
开发语言·rust·match·枚举·匹配·内存安全
一个小坑货18 小时前
Cargo Rust 的包管理器
开发语言·后端·rust
bluebonnet2718 小时前
【Rust练习】22.HashMap
开发语言·后端·rust
VertexGeek20 小时前
Rust学习(八):异常处理和宏编程:
学习·算法·rust