RUST 的数据类型
整数类型
无符号整数
类型 范围 u8 0~28-1 u16 0~216-1 u32 0~232-1 u64 0~264-1 u128 0~2128-1 usize 0~232-1 or 0-264-1
usize取决于系统位数,32为32,64为64.
有符号整数
类型 范围 i8 -27~27-1 i16 -215~215-1 i32 -231~231-1 i64 -263~263-1 i128 -2127~2127-1 isize -231~231-1 or -263~263-1
isize同上取决于系统位数,32为31,64为63.
浮点类型
类型 | 精度 | 范围 |
---|---|---|
f32 | IEEE 单精度(至少6位小数) | 约-3.4×1038~3.4×1038 |
f64 | IEEE 双精度(至少15位小数) | 约-1.8×10308~1.8×10308 |
布尔类型
- 即 True & False
字符类型
- Rust的字符类型以32位值的形式表示单个Unicode字符
- 这使得它可以支持i18n甚至包括emoji
数组
- 最简单的形式,将数据直接括起来:
[1,1,2,3,5,8,13]
- *不要把数组局限于数;如
["hello", "rust", "love", "you"]
也是一个合法的数组 - 可以通过
[V; N]
来生成一个相同元素的数组;- 其中,V为每个元素的值[Value], N为数据个数[Number].
元组
- 元组不同于数组,元组中的元素可以是任何类型
例如("rust", 520)
是一个元组,它的类型是(&str, i32)
- 访问元组中元素的方法
tup.0, tup.1, tup.2
index从0开始 - *零元组:
()
指针类型
引用
&xx类型的值就是对一个xx值的引用
&T : 不可变引用;
&mut T : 可变引用.
Box
|
|
- box分配的元组在堆内存中,即涉及到所有权
原始指针
*mut T
*const T
星号[*]还可以表示解引用
向量
向量Vec<T>
分配在堆内存上[可变]
|
|
- 以上使用了
vec!
宏创建向量
|
|
- 以上使用
push()
向vec_1
向量中添加元素
切片
以下先创建数组与向量
|
|
首先来介绍普通引用
|
|
以上创建了不可变引用
sv和sa的指针指向源数据而不是创建了新的数组和向量
此时sv
和sa
输出结果和vec_1
和arr_1
相同
若想获得特定的元素或者元素片段,则需要进行切片
切片
可以使用如下语句来将数组或者向量切片
|
|
字符串
字符串字面量
字符串字面量放置于双引号中;例如"hello rust!"
这种形式的数据存储于栈内存中,因此无需考虑所有权机制.
字符串
以下方式创建了字符串(String);
|
|
需要注意的是,字符串(String)存储在堆内存中,因此在使用时需要考虑所有权机制!
下一章将介绍所有权机制!
所有权
rust通过所有权机制而不是垃圾回收机制来确保内存安全
转移
在rust中,给变量赋值的操作通常不会创建新值,而是将新的指针指向旧值(栈数据除外)
|
|
上述代码创建了两个变量为v_1
和v_2
并且他们的值都为Hello rust
,在内存中,这两个变量指向的是同一个地址,同一个数据.
同理,为函数传递参数也是这种结果.
值得注意的是,存储在栈内存中的数据在传参等操作后,原值通常可用(这也称作copy
,也就是会产生新的数据.),而存储在堆内存中的数据经过这样的操作后原值会变为未初始化的状态.
|
|
引用
rust有一种不获取源数据所有权来调用源数据内容的方式叫做引用
可以使用&e
来获得一个对e的引用,和rust的变量部分一样,引用通常也是不可变的,如果要获得可变引用,则需要&mut e
- rust不允许同时存在可变引用和不可变引用,但是允许同时存在多个不可变引用.
- rust也允许对引用进行引用,例如
-
1 2 3 4
struct Points {x: i32, y: i32} let point = Points {x: 1000, y: 2000}; let r: &Points = &point; let rr: &&Points = &r;
如上给定了数据类型,但是rust也可以自行推断使用了几层引用.
- 不允许对生命周期已经结束的数据进行引用例如
-
1 2 3 4 5 6 7
fn main() { { let v_1 = 42; } println!(&v_1); //此处非法,因为已经离开了作用域,v_1已经被释放! }
表达式
表达式语言
在rust中,if和match可以产生值
在c语言中,流程控制工具大多数是语句,而在rust都是表达式
Rust 的 if 表达式可以用来初始化变量
|
|
Rust 的 match 表达式可以作为参数传给函数或宏
|
|
这就解释了Rust为什么不需要类似C语言的那种三元操作符
块与分号
代码块同时也是表达式,代码块的值就是最后一个表达式的值
|
|
None =>
之后的部分是一个块表达式,这里块的值就是最后一个表达式ip.to_string()
的值
声明
通常用let
来声明局部变量
|
|
其中,类型和初始值是可选的(Rust会自动进行类型推断),而分号是必须的.
Rust 中,变量默认不可变,例如下面这段代码是会报错的
|
|
如需声明可变变量,则需要使用let mut
|
|
if 与 match
if很简单,如下
|
|
这里不再过多介绍,接下来是match
match有点像C语言的switch,但是更灵活;
|
|
根据code
的值,四个分支只有一个会执行,其中_
表示任何值;
- 值得注意的是,match的分支是从第一条匹配到最后一条,也就是说如果将第四条放在顶端那么这段代码任意
code
都会输出Error
if let 表达式
if let
表达式只是对match表达式的简写,if let
可以实现的功能完全可以由match
实现
|
|
这个结构实现的效果是:expr
要么匹配pattern
,运行block1
,要么不匹配pattern
,运行block2
循环
Rust中有四种循环实现方式
|
|
循环在rust中也是表达式但是循环产生的值是()
- while循环和C类似
- while let循环和if let类似,要么匹配后运行后面的代码,要么不匹配后退出循环
- loop是死循环,除非遇到
retrun
或者break
或者程序挂了 - for循环,很简单,遍历.
- 一般的,进行有限次循环时通常采用for遍历数组的形式,而不是loop或者while
1 2 3
for i in 0..20 { println!("{i}"); }
return 表达式
return表达式退出当前函数,并且向调用者返回值.
通常使用return;
来代表return ();
函数与方法调用
一般地,有以下规则
|
|
同时,还有对静态方法的调用
|
|
- 静态方法与非静态方法的区别是静态方法通过类型调用,而非静态方法通过值调用
- 方法也可以链式调用
1
Iron::new(router).http("localhost:3000").unwarp();
- 需要注意的是,通常用于函数调用或方法调用的语法不能用于泛型Vec
所以需要使用 ::<T>
,而不是<T>:
例如1
return Vec::<i32>::with_capacily(1000);
字段与元素
|
|
此处还涉及到切片,我们以上提到过这里不再赘述
需要注意的是,在使用a..b
这种结构来表示切片范围时,Rust会将其理解为一个半闭半开区如
|
|
引用操作符
& &mut在之前介绍过,这里依然不再重复