rust 为什么在切片时需要引用?

q3qa4bjr  于 2023-08-05  发布在  其他
关注(0)|答案(3)|浏览(148)

下面的代码编译:

fn main() {
    let slices:&[i32] = &[1,2,3];
    let subSlice = &slices[1..3];
    print!("{:?}\n",subSlice);
}

字符串
但这失败了:

fn main() {
    let slices:&[i32] = &[1,2,3];
    let subSlice = slices[1..3];
    print!("{:?}\n",subSlice);
}
Compiling playground v0.0.1 (/playground)
error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
--> src/main.rs:3:9
 |
3 |     let subSlice = slices[1..3];
  |         ^^^^^^^^ doesn't have a size known at compile-time

的数据
slices已经是用&创建的切片/引用(&[i32])。为什么我必须在&slices[1..3]中再次使用&

raogr8fs

raogr8fs1#

从语言的Angular 来看,对切片的索引访问是根据Index<Idx> trait实现的。
该特征被定义为:

pub trait Index<Idx> where
    Idx: ?Sized,{
    type Output: ?Sized;

    // Required method
    fn index(&self, index: Idx) -> &Self::Output;
}

字符串
现在看起来使用this应该返回对索引元素的引用。
事实上,如果我们直接调用它:

use std::ops::Index;

fn main() {
    let slices:&[i32] = &[1,2,3];
    //let subSlice = slices[1..3];
    let sub_slice: &[i32] = slices.index(1..3);
    print!("{:?}\n", sub_slice);
}


返回的类型确实是&[i32]。(playground link
然而,Index documentation page告诉我们:
container[index]实际上是 *container.index(index)的语法糖
这意味着在您的示例中,返回的切片会自动解引用到一个[i32]中,它是未调整大小的。因此,您需要手动借用它以获得&[i32]

l0oc07j2

l0oc07j22#

这里的主要问题是当你索引slices变量时,它返回的[i32]不是固定长度的。
在这个trait实现中可以看到,它返回[T]而不是&[T]
所以编译器不知道要分配多少内存。编译器告诉你,“嘿,我不知道长度,但我知道的是指针的大小”(一个不可变的引用)。
所以编译器建议你借用[i32],所以最终的类型是&[i32]。这是一个固定长度的指针,因此编译器可以将内存分配到堆栈中。

oxcyiej7

oxcyiej73#

切片通常具有类型[T],没有大小的指示。例如,[i32]没有附加大小信息(例如,与具有[i32; 3],其中3表示大小)。rust在编译时需要大小信息。所以这意味着一个切片必须总是在一个引用后面(因为一个引用有固定的大小,也就是说它是一个指向某个内存的指针)。

相关问题