切片和数组有什么区别?

What is the difference between a slice and an array?

为什么在这个例子中 &[u8]&[u8; 3] 都可以?

fn main() {
    let x: &[u8] = &[1u8, 2, 3];
    println!("{:?}", x);

    let y: &[u8; 3] = &[1u8, 2, 3];
    println!("{:?}", y);
}

The fact that &[T; n] can coerce to &[T] is the aspect that makes them tolerable.

为什么&[T; n]可以强制到&[T]?在其他什么情况下会发生这种强制转换?

[T; n] 是一个长度为 n 的数组,表示为 n 个相邻的 T 个实例。

&[T; n] 纯粹是对该数组的引用,表示为指向数据的瘦指针。

[T]是一个slice,一个unsized类型;它只能通过某种形式的间接使用。

&[T],称为切片,是一种大小类型。它是一个 胖指针 ,表示为指向第一项的指针和切片的长度。

因此,数组的长度在编译时已知,而切片长度是运行时的事情。数组目前在 Rust 中是第二 class 公民,因为不可能形成数组泛型。 [T; 0][T; 1]&c. 的各种特征有手动实现,通常最多 32 个;由于这个限制,切片更普遍有用。 &[T; n] 可以强制到 &[T] 的事实是使他们可以容忍的方面。

对于 [T; 3] 有一个 fmt::Debug 的实现,其中 T 实现了 Debug,对于 &T 有另一个实现,其中 T 实现了 fmt::Debug,因此 u8 实现了 Debug&[u8; 3] 也实现了。

Why can &[T; n] coerce to &[T]? In Rust, when does coercion happen?

它会在需要时强制执行,其他时候不会强制执行。我可以想到两种情况:

  1. 有些东西需要一个 &[T] 而你给它一个 &[T; n] 它会默默地强制执行;
  2. 当你在 [T; n] 上调用 x.starts_with(…) 时,它会观察到 [T; n] 上没有这样的方法,因此 autoref 开始发挥作用并尝试 &[T; n] ,这没有帮助,然后强制开始发挥作用,它尝试 &[T],它有一个名为 starts_with.
  3. 的方法

片段 [1, 2, 3].starts_with(&[1, 2]) 展示了两者。

Why can &[T; n] coerce to &[T]?

另一个答案解释了为什么&[T; n]应该强制转换为&[T],这里我将解释编译器如何计算出&[T; n] 可以 强制转换为 &[T]

four possible coercions in Rust:

  1. 传递性。

    • 如果 T 强制转换为 U 并且 U 强制转换为 V,则 T 强制转换为 V.
  2. 指针弱化:

    • 去除可变性:&mut T&T*mut T*const T
    • 转换为原始指针:&mut T*mut T&T*const T
  3. Deref trait:

    • 如果 T: Deref<Target = U>,则 &T 通过 deref() 方法
    • 强制转换为 &U
    • (类似地,如果 T: DerefMut,则 &mut T 通过 deref_mut() 强制转换为 &mut U
  4. Unsize trait:

    • 如果 Ptr 是 "pointer type"(例如 &T*mut TBoxRc 等) , 和 T: Unsize<U>, 然后 Ptr<T> 强制转换为 Ptr<U>.

    • Unsize 特征自动实现:

      • [T; n]: Unsize<[T]>
      • T: Unsize<Trait> 其中 T: Trait
      • struct Foo<…> { …, field: T }: Unsize< struct Foo<…> { …, field: U }>,前提是 T: Unsize<U>(以及一些使编译器的工作更容易的条件)
    • (Rust 将 Ptr<X> 识别为 "pointer type",如果它实现 CoerceUnsized。实际规则表述为,“if T: CoerceUnsized<U> 然后 T 强制转换为 U”。)

&[T; n] 强制转换为 &[T] 的原因是规则 4:(a) 编译器为每个 [T; n] 生成实现 impl Unsize<[T]> for [T; n],以及 (b) 引用&X 是指针类型。使用这些,&[T; n] 可以 强制转换为 &[T].

我根据 kennytm 和 Chris Morgan 的回答创建了这张图片。它描述了各种概念: