Rust的Slice

String Slice

Slice是对集合数据的局部引用,它的数据结构中包含一个起始元素指针和一个元素总长度字段。

例如,下面是String Slice的用法。

1
2
3
4
5
fn main(){
let s = String::from("hello world");
let ss = &s[6..11];
println!("{}", ss); // 输出"world"
}

上面的ss是一个Slice,它是s的局部引用。ss对应的结构中,起始指针指向s的index=6,长度为5。

Slice的范围采用左闭右开的方式,即包含起始位置,不包含结束位置。例如&s[0..5]表示引用从index=0到index=4(不包含index=5)的元素。

可省略起始位置,此时等价于起始位置为0,也可以省略结束位置,等价于引用到结尾,两者都省略时表示获取整个字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fn main(){
let s = String::from("hello world");

// 等价
let s1 = &s[0..5];
let s2 = &s[..5];

// 等价
let s3 = &s[6..];
let s4 = &s[6..s.len()];

// 等价
let s5 = &s[..];
let s6 = &s[0..s.len()];
}

注意,slice的边界索引必须是合理的,不能左越界到第一个元素的左边,也不能右越界到最后一个元素的右边,也不能使用负数索引。

字符串字面量实际上就是String的Slice。String Slice的类型表示为&str

例如,《The Rust Programming Language》中给出的一个示例,找出字符串中第一个单词(即空格左边),如果没有找到空格则返回整个字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fn main() {
let s = String::from("hello world");
println!("{}", first_word(&s[..]));
println!("{}", first_word("HELLO WORLD"));
}

fn first_word(s: &str) -> &str { // 注意类型是&str
for (i, &item) in s.as_bytes().iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}

其他类型的Slice

除了字符串Slice,其他容器类型也支持Slice操作。

例如,对于数组来说,它的Slice用法如下:

1
2
let a = [1,2,3,4,5];
let as = &a[0..3]; // [0,1,2]

这个Slice的类型是&[i32]。它跟字符串Slice的工作方式一样,存储第一个集合元素的引用和一个集合总长度。