其中一个rustlings在基元is about slices上进行了练习。
当我试图解决这个问题时,我首先使用[start...end]
语法将切片放入给定的数组中
fn slice_out_of_array() {
let a: [u8; 5] = [1, 2, 3, 4, 5];
let nice_slice = a[1..4];
assert_eq!([2, 3, 4], nice_slice)
}
编译器抱怨并告诉我:
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> exercises/primitive_types/primitive_types4.rs:10:9
|
10 | let nice_slice = a[1..4];
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
= note: all local variables must have a statically known size
= help: unsized locals are gated as an unstable feature
help: consider borrowing here
|
10 | let nice_slice = &a[1..4];
| +
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
运行rustc --explain E0277
并没有真正回答我的问题。它解释了当函数指定参数应该实现trait时,参数不实现trait意味着什么。这对我来说很清楚,但我不完全清楚这里出了什么问题。
这是我认为正在发生的事情,但我想听听别人的意见。
1.编译器无法从切片语法中计算出生成的切片有多大,因此无法在堆栈上分配适当的空间。
1.默认情况下,切片是基元,位于堆栈而不是堆中。
1.如果我采纳这个建议,添加&
,编译器就会在堆栈上推送一个引用--大小已知--指向堆栈上的原始数组,这样就解决了问题。
这是正确的吗?是否存在这样一种情况,我可以取一个切片,而不添加&
符号?
1条答案
按热度按时间xqk2d5yq1#
编译器无法从切片语法中计算出生成的切片有多大,因此无法在堆栈上分配适当的空间。
这是真的,我们说切片是Dynamically Sized Types (DSTs),或者 * 它们不是
Sized
*,或者 * 它们没有实现Sized
trait *(这就是为什么rustc给你E0277,type不实现trait)。默认情况下,切片是基元,位于堆栈而不是堆中。
这并不精确:slice是原语,但是Rust原语和其他任何对象一样,也可以存在于堆中,只是你试图移动它,所以编译器需要在堆栈中为它保留空间。
如果我采纳这个建议,添加
&
,编译器就会在堆栈上推送一个引用--大小已知--指向堆栈上的原始数组,这样就解决了问题。是的。本质上,编译器只是偏移地址并缩短长度。对slice的引用是一对(地址,长度)。
是否存在这样的情况:我可以取一个切片,而不添加
&
符号?是也不是。
不能,因为你总是使用某种类型的引用。所有的DST只能在一个间接引用之后(一个引用,一个
Box
,一个Rc
...)。当然也可以,因为你并不总是需要添加
&
符号,有时候编译器会帮你添加:当你调用切片上的一个方法时,多亏了 * autoref *:您也可以将其移动到堆中(但这也需要一个幕后引用):