📜  Rust – 数组(1)

📅  最后修改于: 2023-12-03 14:47:10.496000             🧑  作者: Mango

Rust - 数组

Rust 是一种系统编程语言,其拥有静态类型系统、高性能和内存安全等特点。在 Rust 中,数组是一种固定长度,且所有元素类型相同的数据结构。本文将介绍 Rust 中的数组概念、使用方法、特性以及注意点等。

数组定义

在 Rust 中,数组的定义需要指定数组的长度和元素类型。

// 定义一个包含5个元素的整型数组
let numbers: [i32; 5] = [1, 2, 3, 4, 5];

// 定义一个包含3个元素的布尔型数组
let bools: [bool; 3] = [true, false, true];

Rust 中还支持简写,当数组的长度和元素类型都已知时,可以直接使用 [] 进行定义,Rust 编译器会自动推断出数组的长度。

// 根据元素直接推断出数组的长度
let numbers = [1, 2, 3, 4, 5];

// 根据元素直接推断出数组的元素类型和长度
let bools = [true, false, true];
数组访问

通过数组的下标,可以访问到数组中的元素。Rust 中的数组下标从0开始。

// 定义一个包含3个元素的数组
let fruits = ["apple", "banana", "pear"];

// 访问数组中的元素
let first_fruit = fruits[0]; // "apple"
let second_fruit = fruits[1]; // "banana"
let third_fruit = fruits[2]; // "pear"

注意,在 Rust 中,数组下标越界会导致编译错误,这也是 Rust 中安全的体现之一。

let fruits = ["apple", "banana", "pear"];

// 下标越界,无法通过编译
let fourth_fruit = fruits[3]; // error: index out of bounds: the len is 3 but the index is 3
数组特性
不可变性

Rust 中的数组是不可变的(immutable)---即一旦定义,则不能改变其长度和元素值(这与 Rust 中的可变性、可变绑定等概念区分开)。如果需要改变数组中的元素,则需要使用 Rust 中的其他数据结构,例如向量(Vector)等。

let numbers = [1, 2, 3, 4, 5];

// 下面的语句是错误的,不能改变数组中的值
numbers[0] = 0; // error: cannot assign to immutable indexed content `numbers[..]`
可以包含函数指针

在 Rust 中,数组可以包含函数指针。这可以为 Rust 程序员提供更加灵活的编程体验。

// 定义一个包含3个元素的函数指针数组
let functions: [fn(i32) -> i32; 3] = [
    |x| x + 1, 
    |x| x * 2, 
    |x| x.pow(2)
];

// 调用数组中的函数指针
assert_eq!(functions[0](2), 3);
assert_eq!(functions[1](2), 4);
assert_eq!(functions[2](2), 4);
数组长度

Rust 中的数组长度是一个编译时常量。这意味着在编译时就已经确定了数组的长度,并且大小不能改变。

let numbers = [1, 2, 3, 4, 5];
let len_of_numbers = numbers.len(); // 获取数组长度

// 下面的语句是错误的,数组长度不能改变
numbers.resize(10, 0); // error: no method named `resize` found for array `[i32; 5]` in the current scope
遍历数组

Rust 提供多种遍历数组的方式,例如使用 for 循环、迭代器等。

let numbers = [1, 2, 3, 4, 5];

// 使用 for 循环遍历数组
for n in &numbers {
    println!("{}", n);
}

// 使用迭代器遍历数组
numbers.iter().for_each(|n| println!("{}", n));
注意事项
内存分配

Rust 中的数组是栈分配(stack-allocated)的。这意味着数组中元素的内存空间是在定义时就已经分配的,而不是在运行时动态分配,因此数组长度在定义时就必须确定。

// 定义一个包含1000个元素的数组
let numbers = [0; 1000]; 

当数组长度很大时,会导致占用大量内存的问题。此时,可以使用 Rust 中的动态数组结构:向量(Vector)。

模式匹配

Rust 中的模式匹配(pattern matching)可以帮助程序员快速地从数组中获取多个元素。

let numbers = [1, 2, 3, 4, 5];

// 从数组中获取前3个元素
let [a, b, c, ..] = numbers;

// 从数组中获取最后2个元素
let [.., d, e] = numbers;

但是,当数组中的元素个数和模式匹配的元素个数不一致时,会导致编译错误。

let numbers = [1, 2, 3, 4, 5];

// 模式匹配时,左侧和右侧的元素个数不一致,无法通过编译
let [a, b, c] = numbers; // error: pattern requires 3 elements but array has 5