英文:
Rustlings slice primitives
问题
这是我理解的情况:
-
编译器无法从切片语法中确定结果切片的大小,因此无法在栈上分配正确的空间。
-
默认情况下,切片是原始类型,存储在栈上而不是堆上。
-
如果我采纳建议并添加
&
,编译器会在栈上推送一个引用 -- 引用的大小是已知的 -- 指向已经在栈上的原始数组。这解决了问题。
在有些情况下,你可以获取一个切片而不添加&
符号。例如,在函数的参数中,可以传递一个切片作为引用,而不需要额外的符号。
英文:
One of the rustlings exercises on primitive is about slices.
When I tried to solve this exercise I started by using the [start...end]
syntax to take a slice into the given array as such
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)
}
The compiler complains and tells me:
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`.
running rustc --explain E0277
doesn't really answer my question. It explains what it means for an argument not to implement a trait when the function specifies it should. That is clear to me, but i am not completely clear on what is going wrong here.
This is what i think is happening, but I'd like to hear other's opinions.
-
The compiler can't figure out from the slice syntax how big the resulting slice will be and so it can't allocate the proper space on the stack.
-
By default slices are primitives and live on the stack instead of the heap.
-
If I take the suggestion and add
&
the compiler pushes on the stack a reference -- which has a known size -- to the original array already on the stack. This solves the problem.
Is this correct? Is there a case where i can take a slice and not add the &
symbol?
答案1
得分: 1
以下是翻译的内容:
The compiler can't figure out from the slice syntax how big the resulting slice will be and so it can't allocate the proper space on the stack.
编译器无法从切片语法中确定结果切片的大小,因此无法在堆栈上分配适当的空间。
This is true. We say that slices are Dynamically Sized Types (DSTs), or that they are not Sized
, or that they do not implement the Sized
trait (this is the reason rustc gives you E0277, type does not implement trait).
这是正确的。我们说切片是动态大小类型(DSTs),或者说它们不是Sized
,或者说它们不实现Sized
特性(这就是为什么rustc会报错E0277,类型没有实现特性)。
By default slices are primitives and live on the stack instead of the heap.
默认情况下,切片是基本类型,并存储在堆栈上,而不是堆上。
This is not precise: slices are primitives, but Rust primitives, like any other object, can also live on the heap. It is just that you are trying to move it, so the compiler needs to reserve space for it on the stack.
这不是很精确:切片是基本类型,但与任何其他对象一样,Rust基本类型也可以存在于堆上。只是你试图移动它,所以编译器需要在堆栈上保留空间。
If I take the suggestion and add
&
the compiler pushes on the stack a reference -- which has a known size -- to the original array already on the stack. This solves the problem.
如果我采纳建议并添加&
,编译器会在堆栈上推送一个引用——它具有已知大小——指向已经在堆栈上的原始数组。这解决了问题。
Yes. Essentially, the compiler just offsets the address and shortens the length. A reference to slice is a pair of (address, length).
是的。本质上,编译器只是偏移地址并缩短长度。切片的引用是一个地址和长度的配对。
Is there a case where I can take a slice and not add the
&
symbol?
是否存在一种情况,我可以获取切片而不添加&
符号?
Yes and no.
是和否。
No, because you always take a reference of some kind. All DSTs can only come behind an indirection (a reference, a Box
, a Rc
...).
不,因为你总是要获取某种类型的引用。所有的DST只能在一个间接层之后出现(一个引用、一个Box
、一个Rc
...)。
But also yes, because you do not always need to add the &
symbol. Sometimes the compiler is doing it for you: when you call a method on the slice, thanks to autoref:
但也是的,因为你并不总是需要添加&
符号。有时编译器会为你做这个工作:当你在切片上调用方法时,由于自动引用(autoref):
fn slice_out_of_array() {
let a: [u8; 5] = [1, 2, 3, 4, 5];
a[1..4].is_empty(); // Just an example. Equivalent to:
(&a[1..4]).is_empty();
}
你也可以将其移到堆上(但这在底层也需要引用):
fn slice_out_of_array() {
let a: [u8; 5] = [1, 2, 3, 4, 5];
let b: Box<[u8]> = a[1..4].into();
}
英文:
> The compiler can't figure out from the slice syntax how big the resulting slice will be and so it can't allocate the proper space on the stack.
This is true. We say that slices are Dynamically Sized Types (DSTs), or that they are not Sized
, or that they do not implement the Sized
trait (this is the reason rustc gives you E0277, type does not implement trait).
> By default slices are primitives and live on the stack instead of the heap.
This is not precise: slices are primitives, but Rust primitives, like any other object, can also live on the heap. It is just that you are trying to move it, so the compiler needs to reserve space for it on the stack.
> If I take the suggestion and add &
the compiler pushes on the stack a reference -- which has a known size -- to the original array already on the stack. This solves the problem.
Yes. Essentially, the compiler just offsets the address and shorten the length. A reference to slice is a pair of (address, length).
> Is there a case where i can take a slice and not add the &
symbol?
Yes and no.
No, because you always take a reference of some kind. All DSTs can only come behind an indirection (a reference, a Box
, a Rc
...).
But also yes, because you does not always need to add the &
symbol. Sometimes the compiler is doing it for you: when you call a method on the slice, thanks to autoref:
fn slice_out_of_array() {
let a: [u8; 5] = [1, 2, 3, 4, 5];
a[1..4].is_empty(); // Just an example. Equivalent to:
(&a[1..4]).is_empty();
}
You can also moves it to the heap (but this also takes a reference under the hood):
fn slice_out_of_array() {
let a: [u8; 5] = [1, 2, 3, 4, 5];
let b: Box<[u8]> = a[1..4].into();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论