Rust中数组简介
数组(Array)是一种固定大小的、相同类型元素的集合:
- 固定长度:长度在编译时确定,无法动态改变;数组的长度
N是类型的一部分(如[i32; 5]和[i32; 6]是完全不同的类型)。 - 栈上分配:内存直接分配在栈上(与堆分配的
Vec<T>不同);且是连续存储,因此访问速度快,但不适合存储大量数据(栈空间有限)。 - 类型安全:所有元素必须是同一类型。
- 边界检查:访问时自动检查索引是否越界(panic 保护)。
定义与初始化
数组的语法形式为 [T; N]:
T是数组中元素的类型(所有元素必须是同一类型);N是数组的长度(必须是编译时已知的整数常量,不可动态修改)。
初始化方式可以:
- 直接初始化:列出所有元素初始化数组(元素数量需与指定长度一致);
- 重复值初始化:使用
[值; 长度]可初始化数组元素为全部相同的值; - 默认值初始化:使用默认值初始化数组(需要元素实现Default)
// 定义一个包含5个i32类型元素的数组
let nums: [i32; 5] = [1, 2, 3, 4, 5];
// 类型可省略(编译器会自动推断)
let fruits = ["apple", "banana", "cherry"]; // 类型为 [&str; 3]// 创建一个包含10个0的i32数组
let zeros = [0; 10]; // 类型为 [i32; 10]
// 创建一个包含3个"hello"的字符串切片数组
let greetings = ["hello"; 3]; // 类型为 [&str; 3]let arr: [String; 3] = Default::default(); // ["", "", ""]
空数组
空数组(empty array)是合法的,其长度为 0:
let empty1: [i32; 0] = [];
let empty2 = [(); 0]; // 0 个 unit 类型元素
let empty3 = [0; 0]; // 重复 0 次,结果也是空数组
注意:[expr; 0] 是允许的,但 expr 仍会被求值一次然后立即丢弃。
空数组不包含任何元素,但在某些场景下非常有用
- 泛型编程中的占位符;
- 满足类型系统要求:API需要传入数组,而没有数据时;
- 零成本抽象:不占用栈空间,编译器可完全优化掉,适合用于标记或类型级编程;
- 与 FFI 或底层内存操作配合
访问
Rust 不允许在安全代码中使用未初始化的内存。尝试访问一个未初始化的数组,编译器会报错或导致未定义行为。
索引访问
数组元素通过索引访问,索引从 0 开始。Rust 会在运行时检查索引是否越界,若越界会直接触发程序崩溃(panic)。
数组默认是不可变的,若需修改元素,需要使用mut声明为可变数组:
let mut nums = [1, 2, 3];
nums[1] = 20; // 修改第二个元素
println!("修改后:{:?}", nums); // 输出:[1, 20, 3]
遍历
通过for循环或迭代器可遍历数组:
// 使用 for 循环
for element in &arr {println!("{}", element);
}// 使用迭代器
arr.iter().for_each(|x| println!("{}", x));
常用方法
常用基础方法:
| 方法 | 功能描述 |
|---|---|
fn len(&self) -> usize | 返回数组长度 |
fn is_empty(&self) -> bool | 检查数组是否为空 |
fn iter(&self) -> Iter<T> | 创建不可变迭代器 |
fn iter_mut(&mut self) -> IterMut<T> | 创建可变迭代器 |
fn as_slice(&self) -> &[T] | 将数组转换为切片 |
fn as_mut_slice(&mut self) -> &mut [T] | 将数组转换为可变切片 |
fn map<F, U>(self, f: F) -> [U; N] | 元素映射转换 |
元素访问
| 方法 | 功能描述 |
|---|---|
fn get<I>(&self, index: I) -> Option<&T> | 安全索引访问 |
fn get_mut<I>(&mut self, index: I) -> Option<&mut T> | 安全可变索引访问 |
fn first(&self) -> Option<&T> | 获取第一个元素 |
fn last(&self) -> Option<&T> | 获取最后一个元素 |
fn first_mut(&mut self) -> Option<&mut T> | 获取可变首元素 |
fn last_mut(&mut self) -> Option<&mut T> | 获取可变尾元素 |
操作与转换
| 方法 | 功能描述 |
|---|---|
fn swap(&mut self, a: usize, b: usize) | 交换两个位置的元素 |
fn reverse(&mut self) | 反转数组元素顺序 |
fn fill(&mut self, value: T) | 填充相同值 |
fn clone_from_slice(&mut self, src: &[T]) | 从切片克隆数据(需等长) |
fn copy_from_slice(&mut self, src: &[T]) | 从切片复制数据(需Copy trait) |
搜索与判断方法
| 方法签名 | 功能描述 |
|---|---|
fn contains(&self, x: &T) -> bool | 检查是否包含元素(需PartialEq) |
fn starts_with(&self, needle: &[T]) -> bool | 检查前缀 |
fn ends_with(&self, needle: &[T]) -> bool | 检查后缀 |
fn binary_search(&self, x: &T) -> Result<usize, usize> | 二分查找(需有序) |
数组切片
数组本身长度固定,但其切片(&[T])是动态长度的视图,可灵活处理数组的部分元素。切片是数组的引用,不拥有数据所有权,常用于函数参数传递(兼容不同长度的数组)。
let nums = [1, 2, 3, 4, 5];// 截取从索引1到3(不包含3)的元素,生成切片
let slice = &nums[1..3]; // 类型为 &[i32],值为 [2, 3]// 函数接受切片作为参数(可处理任意长度的i32数组)
fn print_slice(slice: &[i32]) {println!("切片内容:{:?}", slice);
}print_slice(&nums); // 传递整个数组的切片,输出:[1, 2, 3, 4, 5]
print_slice(slice); // 传递部分切片,输出:[2, 3]
常用方法
| 方法 | 功能描述 | 示例 |
|---|---|---|
fn windows(&self, size: usize) -> Windows<T> | 滑动窗口迭代器 | [1,2,3].windows(2)→ [1,2], [2,3] |
fn chunks(&self, size: usize) -> Chunks<T> | 固定大小分块迭代器 | [1,2,3,4].chunks(2)→ [1,2], [3,4] |
fn split_at(&self, mid: usize) -> (&[T], &[T]) | 分割数组为两个切片 | [1,2,3].split_at(1)→ (&[1], &[2,3]) |
fn split_first(&self) -> Option<(&T, &[T])> | 分离首元素和剩余部分 | [1,2].split_first()→ (Some(&1), &[2]) |
fn split_last(&self) -> Option<(&T, &[T])> | 分离尾元素和剩余部分 | [1,2].split_last()→ (Some(&2), &[1]) |
