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

时间:2015-06-12 01:59:12

标签: arrays rust slice coercion

为什么此示例中的&[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]?在其他条件下,这种强制发生了吗?

3 个答案:

答案 0 :(得分:24)

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

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

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

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

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

fmt::Debug [T; 3]实施T,其中Debug实施&TT实施fmt::Debug u8实施Debug因为&[u8; 3]实现了&[T; n]&[T]也是如此。

  

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

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

  1. 某些内容需要x.starts_with(…)并且你给它[T; n]它会默默地强制执行;
  2. 当您在[T; n]上致电&[T; n]时,会发现&[T]上没有此类方法,因此autoref开始播放并尝试starts_with,没有帮助,然后强制发挥作用,它会尝试[1, 2, 3].starts_with(&[1, 2]),它有一个名为tbl <- prop.table(table(counts1)) left <- -0.4 + do.call('seq', as.list(range(counts1))) right <- left + (2 * 0.4) bottom <- rep(0, length(left)) top <- tbl xlim <- c(-0.5, 0.5) + range(counts1) nf <- layout(mat = matrix(c(1,2),2,1, byrow=TRUE), height = c(3,1)) par(mar=c(3.1, 3.1, 1.1, 2.1)) plot(NA, xlim=xlim, ylim=c(0, max(tbl))) rect(left, bottom, right, top, col='gray') boxplot(counts1, horizontal=TRUE, outline=TRUE, ylim=xlim, frame=F, width = 10) 的方法。
  3. 代码段dh $@ 演示了两者。

答案 1 :(得分:9)

  

为什么&[T; n]可以强制&[T]

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

four possible coercions in Rust

  1. 传递性。

    • 如果T强迫UU胁迫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通过&U方法强制deref()
    • (同样,如果T: DerefMut,则&mut T通过&mut U强制deref_mut()
  4. Unsize trait

    • 如果Ptr是&#34;指针类型&#34; (例如&T*mut TBoxRc等)和T: Unsize<U>,然后Ptr<T>强制Ptr<U>。< / p>

    • 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>识别为&#34;指针类型&#34;如果它实现CoerceUnsized。实际规则表示为“ if {{1}然后T: CoerceUnsized<U>强迫T “。)

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

答案 2 :(得分:0)

enter image description here

我根据@Shepmaster和Chris Morgan的答案粘贴了一张便笺图片,描述了各种概念。