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,强制何时发生?
它会在需要时强制执行,而且不会在其他时间强制执行.我可以想到两个案例:
&[T]你给它一个&[T; n]它会默默地胁迫;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].
及物.
T强迫U和U胁迫V,则T胁迫V.指针弱化:
&mut T→ &T和*mut T→*const T&mut T→ *mut T和&T→*const TT: Deref<Target = U>,则&T强制&U通过该deref()方法T: DerefMut,然后&mut T强制&mut U通过deref_mut())如果Ptr是一个"指针"(例如&T,*mut T,Box,Rc等等),和T: Unsize<U>,然后Ptr<T>强制转换到Ptr<U>.
该Unsize特征自动实现为:
[T; n]: Unsize<[T]>T: Unsize<Trait> 哪里 T: Traitstruct 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 的回答创建了这张图片。它描述了各种概念: