数组和切片
数组是一种存储在连续内存中的相同类型 T 的对象集合。 数组使用方括号 [] 创建,其长度在编译时已知, 是其类型签名 [T; length] 的一部分。
切片类似于数组,但其长度在编译时未知。切片是一个双字对象: 第一个字是指向数据的指针,第二个字是切片的长度。字的大小与 usize 相同, 由处理器架构决定,例如在 x86-64 上是 64 位。切片可用于借用数组的一部分, 其类型签名为 &[T]。
use std::mem;
// 此函数借用一个切片。
fn analyze_slice(slice: &[i32]) {
println!("切片的第一个元素:{}", slice[0]);
println!("切片有 {} 个元素", slice.len());
}
fn main() {
// 固定大小的数组(类型签名是多余的)。
let xs: [i32; 5] = [1, 2, 3, 4, 5];
// 所有元素可以初始化为相同的值。
let ys: [i32; 500] = [0; 500];
// 索引从 0 开始。
println!("数组的第一个元素:{}", xs[0]);
println!("数组的第二个元素:{}", xs[1]);
// `len` 返回数组中元素的数量。
println!("数组中的元素数量:{}", xs.len());
// 数组是栈分配的。
println!("数组占用 {} 字节", mem::size_of_val(&xs));
// 数组可以自动借用为切片。
println!("将整个数组借用为切片。");
analyze_slice(&xs);
// 切片可以指向数组的一部分。
// 它们的形式是 [起始索引..结束索引]。
// `起始索引` 是切片中的第一个位置。
// `结束索引` 是切片中最后一个位置的后一个位置。
println!("借用数组的一部分作为切片。");
analyze_slice(&ys[1 .. 4]);
// 空切片 `&[]` 的示例:
let empty_array: [u32; 0] = [];
assert_eq!(&empty_array, &[]);
assert_eq!(&empty_array, &[][..]); // 同样的操作,但更详细
// 可以使用 `.get` 安全地访问数组,它返回一个 `Option`。
// 可以像下面这样对其进行匹配,或者使用 `.expect()`。
// 如果你希望程序在访问越界时优雅地退出而不是继续执行,
// 可以使用 `.expect()`。
for i in 0..xs.len() + 1 { // 糟糕,访问超出了数组范围!
match xs.get(i) {
Some(xval) => println!("{}: {}", i, xval),
None => println!("慢着!{} 超出范围了!", i),
}
}
// 使用常量值对数组的越界索引会导致编译时错误。
//println!("{}", xs[5]);
// 对切片的越界索引会导致运行时错误。
//println!("{}", xs[..][5]);
}