Rust专项——数组深度解析:固定大小集合的全面指南
·
引言
数组是编程中最基础的数据结构之一。在Rust中,数组(array)是一个固定大小的、同类型的元素集合,所有元素存储在栈上,具有零成本抽象的优势。理解数组对于掌握Rust的类型系统和内存管理至关重要。
本文将深入探讨Rust数组的所有方面,包括:
- 数组的基础概念和特性
- 数组的创建和初始化方式
- 数组元素的访问和修改
- 数组与切片的关系
- 数组的常用操作方法
- 多维数组的使用
- 数组与其他集合类型的对比
- 性能考虑和最佳实践
通过本文的学习,你将能够:
- 熟练创建和使用数组
- 理解数组的内存布局
- 掌握数组的各种操作方法
- 理解数组与切片、向量的区别
- 在实际项目中正确选择数组
1. 数组基础
1.1 什么是数组?
数组是一个固定大小的、同类型的元素集合,所有元素连续存储在内存中:
fn main() {
// 定义一个数组
let arr: [i32; 5] = [1, 2, 3, 4, 5];
println!("数组: {:?}", arr);
println!("数组大小: {} 字节", std::mem::size_of::<[i32; 5]>());
}

数组的关键特性:
- 固定大小:创建时大小确定,不能改变
- 同类型元素:所有元素必须是相同类型
- 栈分配:数组存储在栈上(小数组)
- 连续内存:元素在内存中连续存储
- 编译时大小:大小必须在编译时确定
1.2 数组类型语法
数组类型的语法:[类型; 长度]
fn main() {
// 类型注解示例
let arr1: [i32; 5] = [1, 2, 3, 4, 5]; // 5个i32
let arr2: [f64; 3] = [1.0, 2.0, 3.0]; // 3个f64
let arr3: [char; 4] = ['a', 'b', 'c', 'd']; // 4个char
let arr4: [bool; 2] = [true, false]; // 2个bool
let arr5: [&str; 3] = ["a", "b", "c"]; // 3个&str
println!("{:?}", arr1);
println!("{:?}", arr2);
}

2. 数组的创建方式
2.1 显式初始化
fn main() {
// 方式1:指定每个元素
let arr1 = [1, 2, 3, 4, 5];
// 方式2:指定类型和元素
let arr2: [i32; 5] = [10, 20, 30, 40, 50];
// 方式3:混合类型(会统一为相同类型)
let arr3 = [1, 2, 3]; // 类型推断为 [i32; 3]
println!("{:?}", arr1);
println!("{:?}", arr2);
println!("{:?}", arr3);
}

2.2 相同值初始化
使用 [值; 长度] 语法创建所有元素相同的数组:
fn main() {
// 创建5个0
let zeros: [i32; 5] = [0; 5];
println!("{:?}", zeros); // [0, 0, 0, 0, 0]
// 创建10个true
let bools = [true; 10];
println!("{:?}", bools);
// 创建3个字符串
let strings = ["hello"; 3];
println!("{:?}", strings); // ["hello", "hello", "hello"]
// 创建浮点数数组
let floats = [3.14; 5];
println!("{:?}", floats);
}

2.3 从向量转换
fn main() {
let vec = vec![1, 2, 3, 4, 5];
// 将向量转为数组(需要明确大小)
// 注意:长度必须匹配,否则编译错误
// let arr: [i32; 5] = vec.try_into().unwrap();
// 或者使用数组切片
let slice: &[i32] = &vec;
println!("{:?}", slice);
}

2.4 数组字面量
fn main() {
// 空数组(长度0)
let empty: [i32; 0] = [];
println!("空数组长度: {}", empty.len());
// 单元素数组
let single = [42];
println!("单元素数组: {:?}", single);
// 大数组(使用相同值)
let large = [0; 1000];
println!("大数组长度: {}", large.len());
}
3. 数组元素的访问
3.1 索引访问
使用方括号 [] 和索引访问数组元素:
fn main() {
let arr = [10, 20, 30, 40, 50];
// 访问单个元素
println!("第一个元素: {}", arr[0]); // 10
println!("第三个元素: {}", arr[2]); // 30
println!("最后一个元素: {}", arr[4]); // 50
// 修改元素(需要mut)
let mut arr2 = [1, 2, 3, 4, 5];
arr2[0] = 100;
println!("修改后: {:?}", arr2); // [100, 2, 3, 4, 5]
}
3.2 越界检查
Rust在运行时检查数组越界:
fn main() {
let arr = [1, 2, 3, 4, 5];
// 编译时无法检查,运行时panic
// println!("{}", arr[10]); // panic! index out of bounds
// 安全访问:使用get方法
match arr.get(10) {
Some(value) => println!("值: {}", value),
None => println!("索引超出范围"),
}
// 或者使用get配合unwrap_or
let value = arr.get(10).unwrap_or(&0);
println!("值: {}", value); // 0(默认值)
}
3.3 安全的索引访问
fn main() {
let arr = [10, 20, 30, 40, 50];
// 方式1:使用get方法(返回Option)
if let Some(val) = arr.get(2) {
println!("索引2的值: {}", val);
}
// 方式2:先检查长度
let index = 3;
if index < arr.len() {
println!("索引{}的值: {}", index, arr[index]);
}
// 方式3:使用unwrap_or
let value = arr.get(100).unwrap_or(&-1);
println!("值: {}", value);
}
4. 数组的基本操作
4.1 获取数组长度
fn main() {
let arr = [1, 2, 3, 4, 5];
// 使用len()方法
println!("数组长度: {}", arr.len());
// 使用数组大小
println!("数组大小: {} 字节", std::mem::size_of_val(&arr));
// 计算元素大小
let element_size = std::mem::size_of::<i32>();
let array_size = arr.len() * element_size;
println!("元素大小: {} 字节", element_size);
println!("总大小: {} 字节", array_size);
}
4.2 数组迭代
fn main() {
let arr = [10, 20, 30, 40, 50];
// 方式1:使用for循环和引用
for element in &arr {
println!("{}", element);
}
// 方式2:使用iter()方法
for element in arr.iter() {
println!("{}", element);
}
// 方式3:获取索引和值
for (index, value) in arr.iter().enumerate() {
println!("索引 {}: 值 {}", index, value);
}
// 方式4:可变迭代
let mut arr2 = [1, 2, 3, 4, 5];
for element in arr2.iter_mut() {
*element *= 2;
}
println!("翻倍后: {:?}", arr2); // [2, 4, 6, 8, 10]
}
4.3 数组切片
数组可以创建切片(slice):
fn main() {
let arr = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
// 创建切片
let slice1 = &arr[0..5]; // 索引0到4
let slice2 = &arr[2..7]; // 索引2到6
let slice3 = &arr[..5]; // 从开始到索引4
let slice4 = &arr[5..]; // 从索引5到最后
let slice5 = &arr[..]; // 整个数组的切片
println!("切片1: {:?}", slice1); // [10, 20, 30, 40, 50]
println!("切片2: {:?}", slice2); // [30, 40, 50, 60, 70]
println!("切片3: {:?}", slice3); // [10, 20, 30, 40, 50]
println!("切片4: {:?}", slice4); // [60, 70, 80, 90, 100]
println!("切片5: {:?}", slice5); // 整个数组
}
5. 数组常用方法
5.1 数组查询方法
fn main() {
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// 查找元素
if let Some(pos) = arr.iter().position(|&x| x == 5) {
println!("5在索引: {}", pos);
}
// 检查包含
println!("包含5: {}", arr.contains(&5));
// 查找第一个满足条件的元素
if let Some(val) = arr.iter().find(|&&x| x > 5) {
println!("第一个大于5的数: {}", val);
}
// 查找最后一个满足条件的元素
if let Some(val) = arr.iter().rfind(|&&x| x < 5) {
println!("最后一个小于5的数: {}", val);
}
}
5.2 数组统计方法
fn main() {
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// 求和
let sum: i32 = arr.iter().sum();
println!("和: {}", sum); // 55
// 求积
let product: i32 = arr.iter().product();
println!("积: {}", product); // 3628800
// 求最大值
if let Some(max) = arr.iter().max() {
println!("最大值: {}", max); // 10
}
// 求最小值
if let Some(min) = arr.iter().min() {
println!("最小值: {}", min); // 1
}
// 求平均值
let avg = sum as f64 / arr.len() as f64;
println!("平均值: {:.2}", avg); // 5.50
}
5.3 数组转换方法
fn main() {
let arr = [1, 2, 3, 4, 5];
// 映射到新数组(会创建新数组)
let doubled: Vec<i32> = arr.iter().map(|x| x * 2).collect();
println!("翻倍: {:?}", doubled);
// 过滤
let evens: Vec<i32> = arr.iter().filter(|&&x| x % 2 == 0).copied().collect();
println!("偶数: {:?}", evens);
// 过滤和映射结合
let result: Vec<i32> = arr.iter()
.filter(|&&x| x > 2)
.map(|x| x * x)
.collect();
println!("过滤和平方: {:?}", result); // [9, 16, 25]
}
5.4 数组排序
fn main() {
let mut arr = [5, 2, 8, 1, 9, 3];
// 排序(升序)
arr.sort();
println!("升序: {:?}", arr); // [1, 2, 3, 5, 8, 9]
// 降序排序
let mut arr2 = [5, 2, 8, 1, 9, 3];
arr2.sort_by(|a, b| b.cmp(a)); // 或使用 arr2.sort(); arr2.reverse();
println!("降序: {:?}", arr2); // [9, 8, 5, 3, 2, 1]
// 使用sort_by进行自定义排序
let mut arr3 = [5, 2, 8, 1, 9, 3];
arr3.sort_by(|a, b| (a % 2).cmp(&(b % 2))); // 奇数在前
println!("自定义排序: {:?}", arr3);
}
6. 多维数组
6.1 二维数组
fn main() {
// 方式1:使用数组的数组
let matrix: [[i32; 3]; 3] = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
// 访问元素
println!("matrix[0][0] = {}", matrix[0][0]); // 1
println!("matrix[1][2] = {}", matrix[1][2]); // 6
// 遍历二维数组
for (i, row) in matrix.iter().enumerate() {
for (j, &value) in row.iter().enumerate() {
println!("matrix[{}][{}] = {}", i, j, value);
}
}
// 打印矩阵
for row in matrix.iter() {
println!("{:?}", row);
}
}
6.2 二维数组的创建和初始化
fn main() {
// 创建全零矩阵
let zeros: [[i32; 3]; 3] = [[0; 3]; 3];
println!("零矩阵:");
for row in zeros.iter() {
println!("{:?}", row);
}
// 创建单位矩阵
let mut identity = [[0; 3]; 3];
for i in 0..3 {
identity[i][i] = 1;
}
println!("\n单位矩阵:");
for row in identity.iter() {
println!("{:?}", row);
}
// 创建随机矩阵(示例)
let matrix = [
[1, 2],
[3, 4],
[5, 6],
];
println!("\n矩阵:");
for row in matrix.iter() {
println!("{:?}", row);
}
}
6.3 矩阵运算示例
fn main() {
// 矩阵加法
fn add_matrices(a: [[i32; 3]; 3], b: [[i32; 3]; 3]) -> [[i32; 3]; 3] {
let mut result = [[0; 3]; 3];
for i in 0..3 {
for j in 0..3 {
result[i][j] = a[i][j] + b[i][j];
}
}
result
}
let a = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
let b = [
[9, 8, 7],
[6, 5, 4],
[3, 2, 1],
];
let sum = add_matrices(a, b);
println!("矩阵和:");
for row in sum.iter() {
println!("{:?}", row); // [10, 10, 10], [10, 10, 10], [10, 10, 10]
}
// 矩阵转置
fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] {
let mut result = [[0; 3]; 3];
for i in 0..3 {
for j in 0..3 {
result[j][i] = matrix[i][j];
}
}
result
}
let transposed = transpose(a);
println!("\n转置矩阵:");
for row in transposed.iter() {
println!("{:?}", row);
}
}
7. 数组与其他集合类型的对比
7.1 数组 vs 向量(Vec)
| 特性 | 数组 [T; N] |
向量 Vec<T> |
|---|---|---|
| 大小 | 固定(编译时) | 可变(运行时) |
| 内存位置 | 栈 | 堆 |
| 性能 | 更快(无分配) | 较慢(需要分配) |
| 最大大小 | 受栈限制 | 受内存限制 |
| 使用场景 | 固定大小数据 | 动态大小数据 |
fn main() {
// 数组:固定大小,栈分配
let arr: [i32; 5] = [1, 2, 3, 4, 5];
// arr.push(6); // 错误!数组大小固定
// 向量:可变大小,堆分配
let mut vec = vec![1, 2, 3, 4, 5];
vec.push(6); // ✅ 可以添加元素
println!("{:?}", vec);
// 何时使用数组?
// - 数据大小在编译时已知且固定
// - 需要栈分配的性能优势
// - 小的固定大小集合
// 何时使用向量?
// - 数据大小在运行时确定
// - 需要动态添加/删除元素
// - 大型数据集
}
7.2 数组 vs 切片(Slice)
fn main() {
let arr = [1, 2, 3, 4, 5];
// 数组:有固定大小
println!("数组大小: {}", arr.len());
// 切片:数组的视图,无所有权
let slice: &[i32] = &arr[1..4];
println!("切片: {:?}", slice); // [2, 3, 4]
println!("切片大小: {}", slice.len());
// 切片可以来自数组或向量
let vec = vec![1, 2, 3, 4, 5];
let vec_slice: &[i32] = &vec[1..4];
println!("向量切片: {:?}", vec_slice);
// 函数通常接受切片而不是数组
fn sum(slice: &[i32]) -> i32 {
slice.iter().sum()
}
println!("数组和: {}", sum(&arr));
println!("切片和: {}", sum(slice));
}
8. 数组的实用技巧
8.1 数组解构
fn main() {
let arr = [1, 2, 3, 4, 5];
// 解构数组
let [first, second, third, fourth, fifth] = arr;
println!("{} {} {} {} {}", first, second, third, fourth, fifth);
// 部分解构
let [first, .., last] = arr;
println!("首: {}, 尾: {}", first, last);
// 忽略某些元素
let [a, _, _, _, e] = arr;
println!("{} {}", a, e);
}
8.2 数组作为函数参数和返回值
// 数组作为参数
fn print_array(arr: &[i32; 5]) {
for elem in arr.iter() {
print!("{} ", elem);
}
println!();
}
// 数组作为返回值
fn create_array() -> [i32; 5] {
[1, 2, 3, 4, 5]
}
// 接受任意大小的数组切片(更灵活)
fn process_array(arr: &[i32]) {
println!("处理数组,长度: {}", arr.len());
}
fn main() {
let arr = [10, 20, 30, 40, 50];
print_array(&arr);
let new_arr = create_array();
print_array(&new_arr);
process_array(&arr);
process_array(&arr[1..4]); // 也可以处理切片
}
8.3 数组填充技巧
fn main() {
// 使用循环填充
let mut arr = [0; 10];
for i in 0..10 {
arr[i] = i as i32;
}
println!("{:?}", arr);
// 使用迭代器填充
let arr2: [i32; 10] = (0..10).map(|x| x as i32)
.collect::<Vec<i32>>()
.try_into()
.unwrap();
println!("{:?}", arr2);
// 使用enum填充
#[derive(Debug)]
enum Status {
Active,
Inactive,
Pending,
}
let statuses = [Status::Active, Status::Inactive, Status::Pending];
// 注意:enum也可以用在数组中
}
9. 数组性能考虑
9.1 栈大小限制
fn main() {
// 小数组:栈分配,快速
let small: [i32; 10] = [0; 10];
println!("小数组大小: {} 字节", std::mem::size_of_val(&small));
// 大数组:可能栈溢出
// let large: [i32; 1_000_000] = [0; 1_000_000]; // 危险!
// 大数组应该使用Vec或Box<[T]>
// 安全的大数组(使用Box)
let large: Box<[i32]> = vec![0; 1_000_000].into_boxed_slice();
println!("大数组长度: {}", large.len());
}
9.2 数组 vs Vec 性能对比
fn main() {
// 小数据集:数组更快
let arr: [i32; 100] = [0; 100];
// 大数据集:Vec更合适
let vec = vec![0; 100_000];
// 数组:零开销,栈分配
// Vec:需要堆分配,但可以动态增长
// 性能测试
use std::time::Instant;
let start = Instant::now();
let _arr = [0; 1000];
let duration = start.elapsed();
println!("数组创建时间: {:?}", duration);
let start = Instant::now();
let _vec = vec![0; 1000];
let duration = start.elapsed();
println!("向量创建时间: {:?}", duration);
}
10. 实战示例
示例1:数组工具函数库
mod array_utils {
// 查找数组中的最大值和最小值
pub fn min_max(arr: &[i32]) -> Option<(i32, i32)> {
if arr.is_empty() {
return None;
}
let min = arr.iter().min().copied()?;
let max = arr.iter().max().copied()?;
Some((min, max))
}
// 数组求和
pub fn sum(arr: &[i32]) -> i32 {
arr.iter().sum()
}
// 数组平均值
pub fn average(arr: &[i32]) -> Option<f64> {
if arr.is_empty() {
return None;
}
let sum: i32 = arr.iter().sum();
Some(sum as f64 / arr.len() as f64)
}
// 数组反转(原地)
pub fn reverse<T: Copy>(arr: &mut [T]) {
let len = arr.len();
for i in 0..len / 2 {
arr.swap(i, len - 1 - i);
}
}
// 查找元素索引
pub fn find_index(arr: &[i32], target: i32) -> Option<usize> {
arr.iter().position(|&x| x == target)
}
}
fn main() {
let arr = [10, 5, 8, 3, 15, 2];
match array_utils::min_max(&arr) {
Some((min, max)) => {
println!("最小值: {}, 最大值: {}", min, max);
}
None => println!("数组为空"),
}
println!("和: {}", array_utils::sum(&arr));
if let Some(avg) = array_utils::average(&arr) {
println!("平均值: {:.2}", avg);
}
if let Some(index) = array_utils::find_index(&arr, 8) {
println!("8在索引: {}", index);
}
let mut arr2 = [1, 2, 3, 4, 5];
array_utils::reverse(&mut arr2);
println!("反转后: {:?}", arr2); // [5, 4, 3, 2, 1]
}
示例2:成绩管理系统
struct Student {
name: String,
scores: [f64; 5], // 5门课程的成绩
}
impl Student {
fn new(name: String, scores: [f64; 5]) -> Self {
Self { name, scores }
}
fn average_score(&self) -> f64 {
self.scores.iter().sum::<f64>() / self.scores.len() as f64
}
fn highest_score(&self) -> f64 {
*self.scores.iter().max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap()
}
fn lowest_score(&self) -> f64 {
*self.scores.iter().min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap()
}
fn passed_all(&self) -> bool {
self.scores.iter().all(|&score| score >= 60.0)
}
}
fn main() {
let student = Student::new(
"Alice".to_string(),
[85.0, 90.0, 78.0, 92.0, 88.0]
);
println!("学生: {}", student.name);
println!("成绩: {:?}", student.scores);
println!("平均分: {:.2}", student.average_score());
println!("最高分: {:.2}", student.highest_score());
println!("最低分: {:.2}", student.lowest_score());
println!("全部及格: {}", student.passed_all());
}
示例3:矩阵运算库
mod matrix {
pub type Matrix3x3 = [[f64; 3]; 3];
pub fn create_zero() -> Matrix3x3 {
[[0.0; 3]; 3]
}
pub fn create_identity() -> Matrix3x3 {
let mut m = create_zero();
for i in 0..3 {
m[i][i] = 1.0;
}
m
}
pub fn add(a: Matrix3x3, b: Matrix3x3) -> Matrix3x3 {
let mut result = create_zero();
for i in 0..3 {
for j in 0..3 {
result[i][j] = a[i][j] + b[i][j];
}
}
result
}
pub fn multiply(a: Matrix3x3, b: Matrix3x3) -> Matrix3x3 {
let mut result = create_zero();
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
result[i][j] += a[i][k] * b[k][j];
}
}
}
result
}
pub fn transpose(m: Matrix3x3) -> Matrix3x3 {
let mut result = create_zero();
for i in 0..3 {
for j in 0..3 {
result[j][i] = m[i][j];
}
}
result
}
pub fn print(m: Matrix3x3) {
for row in m.iter() {
println!("{:?}", row);
}
}
}
fn main() {
let a = [
[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
[7.0, 8.0, 9.0],
];
let b = [
[9.0, 8.0, 7.0],
[6.0, 5.0, 4.0],
[3.0, 2.0, 1.0],
];
println!("矩阵A:");
matrix::print(a);
println!("\n矩阵B:");
matrix::print(b);
println!("\nA + B:");
matrix::print(matrix::add(a, b));
println!("\nA * B:");
matrix::print(matrix::multiply(a, b));
println!("\nA的转置:");
matrix::print(matrix::transpose(a));
}
示例4:数据统计分析
fn analyze_data(data: &[i32]) {
if data.is_empty() {
println!("数据为空");
return;
}
let sum: i32 = data.iter().sum();
let count = data.len();
let average = sum as f64 / count as f64;
let max = *data.iter().max().unwrap();
let min = *data.iter().min().unwrap();
// 计算中位数
let mut sorted = data.to_vec();
sorted.sort();
let median = if count % 2 == 0 {
(sorted[count / 2 - 1] + sorted[count / 2]) as f64 / 2.0
} else {
sorted[count / 2] as f64
};
// 计算标准差
let variance: f64 = data.iter()
.map(|&x| (x as f64 - average).powi(2))
.sum::<f64>() / count as f64;
let std_dev = variance.sqrt();
println!("=== 数据分析 ===");
println!("数据: {:?}", data);
println!("数量: {}", count);
println!("和: {}", sum);
println!("平均值: {:.2}", average);
println!("最大值: {}", max);
println!("最小值: {}", min);
println!("中位数: {:.2}", median);
println!("标准差: {:.2}", std_dev);
}
fn main() {
let data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
analyze_data(&data);
println!();
let data2 = [5, 15, 25, 35, 45];
analyze_data(&data2);
}
11. 常见错误与解决方案
错误1:数组大小不匹配
fn main() {
// 错误:数组大小不匹配
// let arr1: [i32; 5] = [1, 2, 3]; // 编译错误!
// 解决1:匹配大小
let arr1: [i32; 3] = [1, 2, 3];
// 解决2:使用向量
let vec1 = vec![1, 2, 3];
// 解决3:使用切片(更灵活)
fn process_data(data: &[i32]) {
println!("处理 {} 个元素", data.len());
}
process_data(&arr1);
process_data(&vec1);
}
错误2:越界访问
fn main() {
let arr = [1, 2, 3, 4, 5];
// 错误:越界访问
// println!("{}", arr[10]); // panic!
// 解决:使用get方法
match arr.get(10) {
Some(val) => println!("值: {}", val),
None => println!("索引超出范围"),
}
// 或先检查长度
let index = 10;
if index < arr.len() {
println!("{}", arr[index]);
} else {
println!("索引 {} 超出范围", index);
}
}
错误3:类型不匹配
fn main() {
// 错误:类型不匹配
// let arr: [i32; 3] = [1.0, 2.0, 3.0]; // f64 != i32
// 解决:统一类型
let arr1: [i32; 3] = [1, 2, 3];
let arr2: [f64; 3] = [1.0, 2.0, 3.0];
// 或转换类型
let arr3: [i32; 3] = [1.0 as i32, 2.0 as i32, 3.0 as i32];
}
错误4:尝试修改不可变数组
fn main() {
// 错误:尝试修改不可变数组
// let arr = [1, 2, 3];
// arr[0] = 10; // 错误!
// 解决:使用mut
let mut arr = [1, 2, 3];
arr[0] = 10;
println!("{:?}", arr); // [10, 2, 3]
}
12. 数组的高级用法
12.1 数组作为常量
const DAYS_IN_WEEK: [&str; 7] = [
"Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday"
];
const MONTHS: [&str; 12] = [
"January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"
];
fn main() {
println!("一周的第一天: {}", DAYS_IN_WEEK[0]);
println!("一年有 {} 个月", MONTHS.len());
for (i, day) in DAYS_IN_WEEK.iter().enumerate() {
println!("第{}天: {}", i + 1, day);
}
}
12.2 数组与模式匹配
fn analyze_array(arr: &[i32; 5]) {
match arr {
[a, b, c, d, e] if a == e => {
println!("首尾相同: {}, {}, {}, {}, {}", a, b, c, d, e);
}
[a, _, _, _, e] if a > e => {
println!("递减趋势");
}
[a, _, _, _, e] if a < e => {
println!("递增趋势");
}
_ => {
println!("其他模式");
}
}
}
fn main() {
analyze_array(&[1, 2, 3, 4, 1]); // 首尾相同
analyze_array(&[10, 5, 3, 2, 1]); // 递减趋势
analyze_array(&[1, 2, 3, 4, 5]); // 递增趋势
}
12.3 固定大小缓冲区
fn process_buffer(buffer: &mut [u8; 256]) {
// 填充缓冲区
for i in 0..256 {
buffer[i] = (i % 256) as u8;
}
// 处理缓冲区
let sum: u32 = buffer.iter().map(|&b| b as u32).sum();
println!("缓冲区总和: {}", sum);
}
fn main() {
let mut buffer = [0u8; 256];
process_buffer(&mut buffer);
}
13. 扩展练习
练习1:数组工具函数
实现查找、反转、排序、去重等数组操作函数。
练习2:矩阵运算
实现完整的矩阵运算库(加法、乘法、转置、行列式)。
练习3:统计计算
实现计算数组的各种统计量(均值、方差、中位数、众数)。
练习4:数组搜索
实现线性搜索、二分搜索(需要排序)、查找所有匹配项。
练习5:数组转换
实现数组与向量、切片之间的转换函数。
14. 总结
核心要点回顾
- 数组特性:固定大小、同类型、栈分配、连续内存
- 创建方式:显式初始化、相同值初始化
[value; len] - 元素访问:索引访问
arr[i]、安全访问arr.get(i) - 数组操作:迭代、切片、统计、转换
- 多维数组:数组的数组
[[T; N]; M] - 性能考虑:栈大小限制、何时使用数组vs向量
关键特性
- ✅ 固定大小:编译时确定,运行时不能改变
- ✅ 栈分配:小数组性能优异
- ✅ 类型安全:所有元素必须同类型
- ✅ 零成本:无运行时开销
选择指南
| 场景 | 推荐 | 原因 |
|---|---|---|
| 固定大小的数据 | 数组 | 性能好,类型安全 |
| 编译时已知大小 | 数组 | 栈分配,速度快 |
| 动态大小数据 | Vec | 可以增长/缩小 |
| 大数组(>栈限制) | Vec或Box<[T]> | 避免栈溢出 |
| 函数参数 | 切片 &[T] |
更灵活 |
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)