3.3.0. 写在正文之前
欢迎来到Rust自学的第三章,一共有6个小节,分别是:
- 变量与可变性
- 数据类型:标量类型
- 数据类型:复合类型(本文)
- 函数和注释
- 控制流:
if else
- 控制流:循环
通过第二章的小游戏(没看的初学者强烈建议看一下),相信你已经学会了基本的Rust语法,而在第三章我们将更深一层,了解Rust中的通用的编程概念。
喜欢的话记得点赞、收藏加关注哦,想要跟着学下去记得关注专栏哦
3.3.1. 复合类型的简介
- 复合类型可以将多个值放在一个类型里
- Rust提供了两种基础的复合类型:元组(Tuple)、数组
3.3.1. 元组(Tuple)
元组的特点:
- 元组可以将多个类型的多个值放在一个类型里
- 元组的长度是固定的:一旦声明就无法改变
创建元组:
- 在小括号里,将值用逗号分开
- 元组中的每个位置都对应一个类型,元组中个元素的类型不必相同
fn main(){
let tup:(u32,f32,i64) = (6657, 0.0721, 114514);
println!("{},{},{}",tup.0,tup.1,tup.2);
//Output: 6657,0.0721,114514
}
获取元组元素值:
- 可以使用模式匹配来结构(destructure)一个元组来获取元素值。
fn main(){
let let tup:(u32,f32,i64) = (6657, 0.0721, 114514);
let (x, y, z) = tup;
println!("{},{},{}", x, y, z);
//Output: 6657,0.0721,114514
}
访问元组的元素:
- 在元组变量后使用点标记法,后接元素的索引号
println!("{},{},{}", tup.0, tup.1, tup.2);
3.3.2. 数组
数组的特点:
- 数组中的每个元素的类型必须相同
- 数组也可以将多个值放入一个类型
- 数组的长度是固定的
声明数组:
- 在中括号里,各值用逗号分开
let a = [1, 1, 4, 5, 1, 4];
数组的用处:
- 如果想把数组放在栈(Stack)上而不是堆(Heap)上,或者想保证有固定数量的元素,这时使用数组更有好处。
- 数组没有Vector灵活(以后会讲)。
- Vector和数组类似,它由标准库;数组由prelude模块(也是标准库的一部分)提供。
- Vector的长度可以改变
- 不确定应该使用数组还是Vector时,大概率应该使用Vector。
数组的类型:
- 数组的类型以
[类型;长度]
的形式表示
let machine:[u32,4] = [6, 6, 5, 7];
声明数组的其他方法:
- 如果数组的每个元素值都相同,那么可以:
- 在中括号里指定初始值
- 然后跟着一个
;
- 最后加上数组的长度
let a = [3;2];
let b = [3, 3, 3];
这个例子中a
和b
的写法是等价的。
访问数组的元素:
- 数组是Stack上分配的的单个块的内存
- 可以使用索引来访问数组的元素
let machine = [6, 6, 5, 7];
let wjq = machine[0];
- 如果访问的索引超出了数组的范围:
cargo build
时会报错,cargo check
时不会- 运行时会报错,因为Rust不会允许其继续访问相应地址的内存。
数组的原理是一块连续的内存,假设数组的第一个元素在内存上的x位置,那么第二个元素的位置就是x加第一个元素的长度,之后的以此类推。
如果索引值超过了数组的实际长度,那么程序就会读取不在数组位置的其他内存位置,而这个地方的值不一定是什么。在C中完全没有边界检查。在C++中普通数组没有,只有std::array
有;在Rust里强制边界检查
特性 | C | C++ | Rust |
---|---|---|---|
内存模型 | 连续 | 连续 | 连续 |
安全性 | 无边界检查 | std::array 有边界检查,普通数组无 | 强制边界检查 |
动态数组支持 | 需要手动管理内存 | std::vector | Vec |
多维数组支持 | 是 | 是 | 是 |
特殊能力 | 简单高效 | STL容器丰富 | 所有权和借用检查 |
但Rust只会对数组进行简单的边界检查,如果将代码写的稍微复杂一点,Rust就无法在编译时检查,只能在运行时进行检查。
let a = 5;
let machine = [6, 6, 5, 7];
let wjq = machine[a];
这个代码Rust会在编译时报错
let a = [1, 9, 10, 4, 5];
let machine = [6, 6, 5, 7];
let wjq = machine[a[4]];
这个代码Rust就不会在编译时报错,但在运行时会报错