在 Rust 中,切片(slice)和字符串切片(string slice)是两种重要的引用类型,用于高效、安全地访问数据的一部分。以下是详细解释:
一、切片类型(Slice Type)
- 定义
切片(Slice)是对一个集合(如数组、Vec
等)中连续元素的引用,它允许你引用集合的一部分,而无需拷贝整个集合。切片是动态大小的类型(DST),通常以引用的形式存在(&[T]
)。 - 语法与特性
- 类型表示为
&[T]
(不可变)或&mut [T]
(可变)。 - 包含两个信息:指向数据的指针和长度(元素数量)。
- 通过范围语法(如
start..end
)创建,范围是左闭右开的([start, end)
)。 - 示例:
let arr = [1, 2, 3, 4, 5];
let slice = &arr[1..4]; // 引用第2到第4个元素:[2, 3, 4]
- 用途
- 高效访问数据的子集(无需拷贝)。
- 作为函数参数,接收任意长度的连续数据。
二、字符串切片类型(String Slice)
- 定义
字符串切片(&str
)是对 UTF-8 编码字符串数据的不可变引用,通常指向String
或字符串字面量(如"hello"
)。 - 语法与特性
- 类型表示为
&str
(不可变)。 - 直接指向字符串的内存地址和长度。
- 必须保证有效性:所有字符均为合法 UTF-8,否则编译错误。
- 示例:
let s = String::from("hello");
let slice = &s[0..2]; // 引用前两个字节:"he"
// 字符串字面量本身就是 &str
let literal: &str = "world";
- 用途
- 高效读取字符串的某部分(如子字符串)。
- 作为函数参数,灵活接收
String
或字面量(更推荐&str
而非&String
)。
三、关键区别
特性 | 普通切片( | 字符串切片( |
数据类型 | 任意类型 | 必须是 UTF-8 字符 |
可变性 | 可不可变( | 仅不可变( |
底层存储 | 连续元素集合(数组、 |
|
四、为什么需要切片?
- 安全性
- 切片会检查范围有效性,避免越界访问。
- 字符串切片保证 UTF-8 合法性。
- 高效性
- 无需拷贝数据,减少内存开销。
- 灵活性
- 函数可接受任意长度的切片参数(如
fn sum(slice: &[i32]) -> i32
)。
五、示例对比
// 普通切片
let numbers = [10, 20, 30, 40];
let num_slice = &numbers[1..3]; // [20, 30]
// 字符串切片
let s = String::from("hello");
let str_slice = &s[0..2]; // "he"
let literal_slice = "rust"; // 类型为 &str
通过切片和字符串切片,Rust 在保证内存安全的同时,提供了高效灵活的数据访问方式。