Rust备忘录
本文章旨在记录 Rust 学习过程中的一些知识。
Cargo
其作用相当于 Rust 的项目管理器和语言编译器。
cargo new project_name:创建名为project_name的项目,文件夹内包含源码文件夹src,编译产物target,.gitignore文件,Cargo.lock文件和Cargo.toml文件。src:内含main.rs初始源代码,将源代码存放此处。target:debug:存放调试版本的编译产物。release:存放发布版本的编译产物。
.gitignore:Git忽略文件。Cargo.lock:锁定依赖版本的文件。Cargo.toml:项目配置文件,包含项目名称、版本、依赖等信息。
cargo build:编译项目,生成调试版本的可执行文件,存放在target/debug目录下。
默认为--debug模式,可通过--release参数生成发布版本,存放在target/release目录下。cargo run:编译并运行项目,等同于先执行cargo build然后运行生成的可执行文件。cargo check:快速检查代码确保可以通过编译。
基础语法
基本数据类型:
整数类型:
类型名称 位数 范围 i8 8 -2^7 ~ 2^7-1 i16 16 -2^15 ~ 2^15-1 i32 32 -2^31 ~ 2^31-1 i64 64 -2^63 ~ 2^63-1 i128 128 -2^127 ~ 2^127-1 isize 与系统位数相同 -2^(n-1) ~ 2^(n-1)-1 u8 8 0 ~ 2^8-1 u16 16 0 ~ 2^16-1 u32 32 0 ~ 2^32-1 u64 64 0 ~ 2^64-1 u128 128 0 ~ 2^128-1 usize 与系统位数相同 0 ~ 2^n-1 浮点数类型:
f32(单精度浮点数),f64(双精度浮点数,默认类型)。布尔类型:
bool,取值为true或false。字符类型:
char,表示单个Unicode字符,占4字节。单元类型:
(),表示没有值的类型,类似于其他语言中的void。
复合数据类型:
- 元组(Tuple):用来将多个不同类型的值组合在一起。
- 数组(Array):用来存储多个相同类型的值,长度固定。
- 切片(Slice):动态大小的视图,引用数组的一部分。
- 结构体(Struct):自定义数据类型,可以包含多个字段。
常变量声明:
1
2
3const a = 1;
let b: i32 = 2;
let mut c = 3;类型声明在常/变量名后面使用
: type,整型默认i32,浮点型默认f64。变量默认为不可变,如果需要变量可变,需要加
mut。如果等号右侧类型确定,则左侧类型可以自动推导。
如果不同类型之间进行初始化,使用
type1::from(small: type2),将 small 从 type1 类型转变为 type2 类型。遮蔽Shadowing:
1
2let x: i32 = 1;
let x: f64 = 1.1;对于一变量名,可重复使用,在这段代码之后使用该变量则为覆盖之后的变量。
IO:
1
2
3
4
5let mut n = String::new();
std::io::stdin()
.read_line(&mut n)
.expect("Failed to read a line");
let n: u32 = n.trim().parse().expect("expect a number");read_line函数读入一行,保存到 n 中,返回一个 Result 类型,使用 expect 函数处理。之后将 n 转换为
u32类型,使用trim函数修剪,使用parse函数转换为想要的值,返回Result<F, F::Err>。语句和表达式:
语句:执行操作但不返回值。如初始化/赋值语句
表达式:计算并产生一个值。
带有返回值的函数:
返回值使用
return关键字,一般函数默认返回最后一个表达式的值,使用->后置函数返回类型。无返回类型函数返回单位类型
(),类似于void。条件分支:
if-else,可以不使用(),包括可以使用||,&&,!。循环:
1
2
3loop {
}1
2for range {
}1
2while condition {
}循环标签:使用
'name':为循环命名,使用continue/break name;即可跳出/退出指定循环。循环返回值:使用
break value;可以让循环语块返回特定值。所有权:
规则:
- Rust 中的每一个值都有一个所有者(owner)。
- 值在任一时刻有且只有一个所有者。
- 当所有者离开作用域,这个值将被丢弃。
浅拷贝和深拷贝:
Rust 中永远默认浅拷贝。
- 对于含有存在于堆中的元素:一旦进行赋值语句,原值可以看作
move到了新值中,原值不可再使用。 - 对于只存在于栈中的元素:浅拷贝和深拷贝无差异,赋值之后仍可以使用。
如果需要深拷贝,可以使用
.clone()成员函数。如果需要赋值后原变量仍可使用,可以实现
Copy trait,如果一个类型中有一部分含有Drop trait,则不允许再添加Copy trait。对于函数,函数传入参数和函数返回值同样可以转移所有权。
变量的所有权总是遵循相同的模式:将值赋给另一个变量时它会移动。当持有堆中数据值的变量离开作用域时,其值将通过drop被清理掉,除非数据被移动为另一个变量所有。
引用与借用:
引用类似于指针,但保证在其生命周期内指向一个特定类型的有效值。引用类型声明:
&type。引用只是单纯指向,而不是拥有。
在引用变量生命周期结束后,不会释放其指向的资源。
创建一个引用的行为称为借用。
引用默认不可变,如需修改引用指向的变量,需声明可变引用:
&mut type。在同一个可变引用的作用域内,不可以再创建另一个可变引用。(避免数据竞争)
在不可变引用的作用域内,不可以再创建可变引用。
Slice切片:
Slice允许引用集合中的一个连续片段,而不引用整个集合。
&set[begin..end],包含该集合中的[begin, end),begin默认为0,end默认为set length。
结构体Struct
定义方式:
1
2
3
4
5
6struct {
name1: type1,
name2: type2,
......
}创建实例:

