Rust - 切片Slice

1,154 阅读3分钟

这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战

Slice类型

Slice数据类型没有所有权,slice允许我们引用集合中一段连续的元素序列而不用引用整个集合。字符串slice(string slice) 是String中 一部分值的引用。如下述代码示例,不是对整个String的引用而是对部分String的引用:

fn main() {
    let s = String::from("hello world");

    let hello = &s[0..5];
    let world = &s[6..11];
}

可以使用一个由中括号中的 [starting_index..ending_index] 指定的 range 创建一个 slice,其中 starting_index 是 slice 的第一个位置,ending_index 则是 slice 最后一个位置的后一个值。在其内部,slice 的数据结构存储了 slice 的开始位置和长度,长度对应于 ending_index 减去 starting_index 的值。所以对于 let world = &s[6..11]; 的情况,world 将是一个包含指向 s 第 7 个字节(从 1 开始)的指针和长度值 5 的 slice。如下图所示:

image-20211123160932958

对于 Rust 的 .. range 语法,如果想要从第一个索引(0)开始,可以不写两个点号之前的值。同样的,如果 slice 包含 String 的最后一个字节,也可以舍弃尾部的数字。如下代码:

// 舍弃开头数字
fn main() {
    let s = String::from("hello");

    let slice = &s[0..2];
    let slice = &s[..2];
}

// 舍弃尾部数字
fn main() {
    let s = String::from("hello");

    let len = s.len();

    let slice = &s[0..len];
    let slice = &s[..];
}

字符串字面值

现在我们知道了Slice,就可以正确的理解字符串字面值了。这里 s 的类型是 &str:它是一个指向二进制程序特定位置的 slice。这也就是为什么字符串字面值是不可变的;&str 是一个不可变引用。

let s = "hello rust";

其他类型的slice

字符串 slice,是针对字符串的。不过也有更通用的 slice 类型,比如数组(array),就和获取一部分字符串一样,如果我们想要引用数组的一部分,也可以和字符串slice一样的操作。

let a = [1, 2, 3, 4, 5];
let slice = &a[1..3];

这个slice变量的类型是&[i32],它跟字符串 slice 的工作方式一样,通过存储第一个集合元素的引用和一个集合总长度。你可以对其他所有集合使用这类 slice。

总结

所有权系统影响了 Rust 中很多其他部分的工作方式。所有权、借用和 slice 这些概念让 Rust 程序在编译时确保内存安全。Rust 语言提供了跟其他系统编程语言相同的方式来控制你使用的内存,但拥有数据所有者在离开作用域后自动清除其数据的功能意味着你无须额外编写和调试相关的控制代码。

结语

文章首发于微信公众号程序媛小庄,同步于掘金

码字不易,转载请说明出处,走过路过的小伙伴们伸出可爱的小指头点个赞再走吧(╹▽╹)