Skip to content

Rust - 切片

切片(slice)是对由其他数据结构拥有的一块连续内存的视图或引用。切片允许你处理集合的一部分,例如数组、向量或 String,而无需复制底层数据。这使得它们高效且强大。

切片的主要特性:

  • 它们借用数据;它们不拥有数据。
  • 它们的大小在运行时确定。
  • 它们以引用方式传递给函数,从而促进高效、所有权感知的代码。

最常见的切片类型是字符串切片(string slice),写作 &str。它是对 String 或字符串字面量的一部分的引用。

let collection = [1, 2, 3, 4, 5];
let slice = &collection[start_index..end_index]; // `end_index` 是排他的(不包含在内)

范围 start..end 创建一个切片,该切片包含从 start 开始到 end 之前(不包括 end)的元素。

fn main() {
let s = String::from("Hello, world!");
// 使用范围语法创建切片
let hello = &s[0..5]; // 或 &s[..5]
let world = &s[7..12]; // 如果你小心的话,也可以是 &s[7..s.len()-1]
let full_slice = &s[..]; // 整个字符串的切片
println!("Slice 1: {}", hello);
println!("Slice 2: {}", world);
println!("Full slice: {}", full_slice);
}
Slice 1: Hello
Slice 2: world
Full slice: Hello, world!

警告: Rust 字符串是 UTF-8 编码的。某些字符占用多个字节。如果你尝试在多字节字符的中间创建字符串切片,你的程序将在运行时崩溃(panic)。切片必须发生在有效的字符边界上。

// 这会导致崩溃(PANIC)!
// 字符 '👋' 是多字节的。
let wave = "👋";
// let slice = &wave[0..1]; // 崩溃:`byte index 1 is not a char boundary`

为了安全地处理字符,最好使用 .chars() 方法进行迭代。

切片在数组和向量上同样适用。i32 值切片的类型是 &[i32]。

fn process_slice(slice: &[i32]) {
println!("Slice has {} elements", slice.len());
println!("First element: {}", slice[0]);
println!("Full slice content: {:?}", slice);
}
fn main() {
let data = [10, 20, 30, 40, 50];
// 传递中间三个元素的切片
process_slice(&data[1..4]); // 借用索引 1、2 和 3 处的元素
}
Slice has 3 elements
First element: 20
Full slice content: [20, 30, 40]

如果你有一个可变集合,可以使用 &mut 创建一个可变切片。可变切片允许你更改它所引用的元素的值。

fn modify_slice(slice: &mut [i32]) {
println!("Original slice: {:?}", slice);
slice[0] = 999; // 修改切片的第一个元素
println!("Modified slice: {:?}", slice);
}
fn main() {
let mut data = [10, 20, 30, 40, 50];
println!("Original array before: {:?}", data);
// 传递一个可变切片
modify_slice(&mut data[1..4]);
println!("Original array after: {:?}", data);
}
Original array before: [10, 20, 30, 40, 50]
Original slice: [20, 30, 40]
Modified slice: [999, 30, 40]
Original array after: [10, 999, 30, 40, 50]

注意修改切片如何直接改变了原始的 data 数组。这就是借用的力量所在。