数组和切片
数组是相同类型 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);
// 切片可以指向数组的一部分。
// 它们的形式为 [起始索引..结束索引]。
// `起始索引` 是切片中的第一个位置。
// `结束索引` 比切片中的最后一个位置大 1。
println!("将数组的一部分作为切片借用。");
analyze_slice(&ys[1..4]);
// 空切片 `&[]` 的示例:
let empty_array: [u32; 0] = [];
assert_eq!(&empty_array, &[]);
assert_eq!(&empty_array, &[][..]); // 相同但更详细
// 可以使用 `.get` 安全地访问数组,它返回一个
// `Option`。可以如下匹配,或者如果你希望程序
// 以友好的消息退出而不是愉快地继续,可以与
// `.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]);
}