切片 (Slices)

回到 Vec 的内存布局:

let mut numbers = Vec::with_capacity(3);
numbers.push(1);
numbers.push(2);
      +---------+--------+----------+
Stack | pointer | length | capacity | 
      |  |      |   2    |    3     |
      +--|------+--------+----------+
         |
         |
         v
       +---+---+---+
Heap:  | 1 | 2 | ? |
       +---+---+---+

我们已经指出 String 不过是伪装的 Vec<u8>
这个相似性应该让你提问:"那 Vec 对应的 &str 是什么?"

&[T]

[T] 是元素类型为 T 的连续序列的切片 (slice)
它最常以借用形式 &[T] 出现。

可以用多种方式从 Vec 创建切片引用:

let numbers = vec![1, 2, 3];
// 通过索引语法
let slice: &[i32] = &numbers[..];
// 通过方法
let slice: &[i32] = numbers.as_slice();
// 或针对元素的子集
let slice: &[i32] = &numbers[1..];

Vec 实现了 Deref 特质,Target[T],因此借助解引用强制转换 (deref coercion) 你可以直接在 Vec 上调用切片方法:

let numbers = vec![1, 2, 3];
// 出乎意料:`iter` 不是 `Vec` 上的方法!
// 它是 `&[T]` 上的方法,但你可以借助解引用强制转换
// 在 `Vec` 上调用它。
let sum: i32 = numbers.iter().sum();

内存布局 (Memory layout)

&[T] 是一个胖指针 (fat pointer),跟 &str 一样。
它由指向切片首元素的指针和切片长度组成。

如果你有一个含三个元素的 Vec

let numbers = vec![1, 2, 3];

然后创建一个切片引用:

let slice: &[i32] = &numbers[1..];

会得到这样的内存布局:

                  numbers                          slice
      +---------+--------+----------+      +---------+--------+
Stack | pointer | length | capacity |      | pointer | length |
      |    |    |   3    |    4     |      |    |    |   2    |
      +----|----+--------+----------+      +----|----+--------+
           |                                    |  
           |                                    |
           v                                    | 
         +---+---+---+---+                      |
Heap:    | 1 | 2 | 3 | ? |                      |
         +---+---+---+---+                      |
               ^                                |
               |                                |
               +--------------------------------+

&Vec<T>&[T] (&Vec<T> vs &[T])

当你需要把一个对 Vec 的不可变引用传给函数时,优先用 &[T] 而非 &Vec<T>
这让函数可以接受任何切片,不一定要由 Vec 支撑。

例如,你可以传 Vec 中元素的子集。 但还不止于此——你也可以传一个数组的切片

let array = [1, 2, 3];
let slice: &[i32] = &array;

数组切片和 Vec 切片是同一个类型:它们都是指向连续元素序列的胖指针。 对数组而言,指针指向的是栈而不是堆,但在使用切片时这无关紧要。

原文链接:英文原文