58、Slices(切片)
Slices(切片)
让我们回顾一下Vec
的内存布局:
let mut numbers = Vec::with_capacity(3);
numbers.push(1);
numbers.push(2);
我们之前学到了String
本质上其实就是Vec<u8>
,从中可以衍生出一个问题:Vec
的&str
等价于什么?
&[T]
[T]
是T类型元素的连续序列的切片。
它最常以借用形式&[T]
使用。
有多种方式可以从Vec
创建切片引用:
let numbers = vec![1, 2, 3];
// Via index syntax 通过索引语法
let slice: &[i32] = &numbers[..];
// Via a method 通过方法
let slice: &[i32] = numbers.as_slice();
// Or for a subset of the elements 或对于元素的子集
let slice: &[i32] = &numbers[1..];
Vec
使用 [T]
作为目标类型实现了 Deref trait
,因此得益于 Deref
强制转换,我们可以直接对 Vec
使用切片(slice)方法。
let numbers = vec![1, 2, 3];
// Surprise, surprise: `iter` is not a method on `Vec`!
// It's a method on `&[T]`, but you can call it on a `Vec`
// thanks to deref coercion.
// 令人惊讶的是:iter 并不是 Vec 上的方法!
// 它实际上是 &[T] 上的方法,但你可以通过 Deref 强制转换在 Vec 上直接调用它。
let sum: i32 = numbers.iter().sum();
怪不得,我之前在Vec
里面找iter()
方法找不到呢
内存布局
&[T]
是一个胖指针,就像&str
一样。
它由指向切片的第一个元素的指针和切片的长度组成。
如果我们有一个包含三个元素的Vec
:
let numbers = vec![1, 2, 3];
然后创建一个切片引用:
let slice: &[i32] = &numbers[1..];
我们就可以得到这样的内存布局:
&Vec<T>
vs &[T]
当我们需要向函数传递一个不可变的Vec
引用时,首选&[T]
而不是&Vec[T]
。
这允许函数接受任何类型的切片,而不一定是由Vec
支持的切片。
例如,我们可以传递Vec
中元素的子集。但他远不止于此——我们还可以传递Array
的切片:
let array = [1, 2, 3];
let slice: &[i32] = &array;
Array
切片和Vec
切片是同一种类型:他们都是指向连续元素序列的胖指针。在arrays
的情况下,指针指向堆栈(stack)而不是堆(heap),但在使用切片时,这并不重要。
练习
这一节的练习比较简单:
// TODO: Define a function named `sum` that takes a reference to a slice of `u32` and returns the sum of all
// elements in the slice.
// TODO:定义一个名为 sum 的函数,该函数接受一个 u32 切片的引用,并返回切片中所有元素的总和。
pub fn sum(num:&[u32])->u32{
num.iter().sum()
}
就是让我们实现一个函数,函数接受一个u32类型的切片,然后返回所有元素的总和,我们使用迭代器和组合器就可以完成那些逻辑,其他的也没有什么很难的地方。
这一节就先到这里了。
阅读剩余
版权声明:
作者:CN059
链接:https://www.cn059.com/2025/09/25/58%e3%80%81slices%ef%bc%88%e5%88%87%e7%89%87%ef%bc%89.html
文章版权归作者所有,未经允许请勿转载。
THE END