切片和数组之间有什么区别?

run*_*ter 26 arrays coercion slice rust

为什么都是&[u8]&[u8; 3]确定在这个例子吗?

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

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

&[T; n]可以胁迫的事实&[T]是使它们可以容忍的方面. - 克里斯摩根

为什么可以&[T; n]胁迫&[T]?在其他条件下,这种强制发生了吗?

Chr*_*gan 27

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

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

[T]是一个切片,一个未分级的类型; 它只能通过某种形式的间接使用.

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

因此,阵列在编译时已知其长度,而切片长度是运行时问题.数组是目前Rust中的二等公民,因为不可能形成数组泛型.有各种性状的手动实现[T; 0],[T; 1],& C.,通常最多32; 由于这种限制,切片通常更有用.&[T; n]可以胁迫的事实&[T]是使它们可以容忍的方面.

还有的实现fmt::Debug[T; 3],其中T工具Debug,另一个是&T地方T工具fmt::Debug,并且使得u8器具Debug,&[u8; 3]也不会.

为什么可以&[T; n]胁迫&[T]?在Rust,强制何时发生?

它会在需要时强制执行,而且不会在其他时间强制执行.我可以想到两个案例:

  1. 什么东西期望一个&[T]你给它一个&[T; n]它会默默地胁迫;
  2. 当你打电话x.starts_with(…)[T; n]它时会发现没有这样的方法[T; n],所以autoref进入游戏并尝试&[T; n],这没有帮助,然后强制发挥作用,它尝试&[T],它有一个方法调用starts_with.

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


ken*_*ytm 11

为什么可以&[T; n]胁迫&[T]

另一个答案解释了为什么&[T; n] 强制执行&[T],在这里我将解释编译器如何解决&[T; n] 可以强制执行的问题&[T].

Rust中四种可能的强制:

  1. 及物.

    • 如果T强迫UU胁迫V,则T胁迫V.
  2. 指针弱化:

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

    • 如果T: Deref<Target = U>,则&T强制&U通过该deref()方法
    • (同样,如果T: DerefMut,然后&mut T强制&mut U通过deref_mut())
  4. Unsize特质:

    • 如果Ptr是一个"指针"(例如&T,*mut T,Box,Rc等等),和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>(以及一些使编译工作更容易的条件)
    • (Ptr<X>如果它实现,Rust会识别为"指针类型" CoerceUnsized.实际规则表示为" 如果T: CoerceUnsized<U>然后T强制执行U ".)

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


ker*_*520 10

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

在此输入图像描述

  • 内存中不存在“n”。对于切片,它位于胖指针中,但对于数组或数组引用,它仅存在于类型中,如“N”;它都是在编译时整理出来的,根本不会在运行时出现。 (12认同)
  • 否则这是一个非常有用的插图!我希望更多的人在解释概念时使用视觉教具。 (2认同)