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

问题描述 投票:21回答:3

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

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

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

&[T; n]可以胁迫&[T]的事实是让他们容忍的方面。 — Chris Morgan

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

arrays rust slice coercion
3个回答
25
投票

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

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

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

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

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

fmt::Debug[T; 3]的实施,其中T实施Debug&T实施Tfmt::Debugu8实施Debug&[u8; 3]也实现&[T; n]

为什么&[T]强迫&[T]?在Rust,强制何时发生?

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

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

片段&[T; n]演示了两者。


11
投票

为什么&[T]强迫&[T; n]

另一个答案解释了为什么&[T]应该强迫&[T; n],在这里我将解释编译器如何解决&[T]可以胁迫four possible coercions in Rust

T

  1. 及物。 如果U强迫UV胁迫T,那么V强迫&mut T
  2. 指针弱化: 消除可变性:&T*mut T*const T&mut T 转换为原始指针:*mut T&T*const TDeref trait
  3. T: Deref<Target = U>: 如果&T,那么&U通过deref()方法强制到T: DerefMut (同样地,如果&mut T,那么&mut U通过deref_mut()强制到Unsize trait
  4. Ptr: 如果&T是一个“指针类型”(例如*mut TBoxRcT: 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]强制执行impl Unsize<[T]> for [T; n]的原因是规则4:(a)编译器为每个[T; n]生成实现&X,并且(b)参考&[T; n]是指针类型。使用这些,&[T]可以胁迫enter image description here


0
投票

qazxswpoi

我根据@Shepmaster和Chris Morgan的回答粘贴了一张便条图,描述了不同的概念。

© www.soinside.com 2019 - 2024. All rights reserved.