我正在努力,非常不成功地玩切片.
我把我的第一个问题减少到:
fn at<'a, T>(slice: &'a [T], index: usize) -> &'a T {
let item = slice[index];
item
}
Run Code Online (Sandbox Code Playgroud)
slice[index]根据文档,我希望返回类型是一个参考:
pub trait Index<Index> {
type Output;
fn index(&'a self, index: &Index) -> &'a <Self as Index<Index>>::Output;
// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
Run Code Online (Sandbox Code Playgroud)
但是,编译器给我一个错误:
Run Code Online (Sandbox Code Playgroud)error[E0308]: mismatched types --> src/main.rs:3:5 | 3 | item | ^^^^ expected reference, found type parameter | = note: expected type `&'a T` found type `T`
我将其解释为意味着item类型与函数的返回类型不匹配(我item仅为调试目的引入,从返回中拆分表达式求值).
如果我将返回类型切换为T,这是类型item,我得到另一个错误消息:
Run Code Online (Sandbox Code Playgroud)error[E0508]: cannot move out of type `[T]`, a non-copy slice --> src/main.rs:2:16 | 2 | let item = slice[index]; | ^^^^^^^^^^^^ | | | cannot move out of here | help: consider using a reference instead: `&slice[index]`
经过修补,我找到了两个解决方法:
fn at<'a, T>(slice: &'a [T], index: usize) -> &'a T {
&slice[index]
// ^
}
fn at<'a, T>(slice: &'a [T], index: usize) -> &'a T {
let ref item = slice[index];
// ^~~
item
}
Run Code Online (Sandbox Code Playgroud)
强制该类型作为参考就可以了.
为什么这些恶作剧首先是必要的?难道我做错了什么?
She*_*ter 12
这是编译器为您做的一些有用的人体工程学设计,以使代码看起来更好一些.
在返回值Index特点是一个参考,但是编译器会自动插入一个提领你当您使用加糖的语法 [].大多数其他语言只会从数组中返回该项(复制它或返回另一个对象的引用,无论什么是合适的).
由于Rust的移动/复制语义的重要性,您不能总是复制一个值,因此在这些情况下,您通常会使用&:
let items = &[1u8, 2, 3, 4];
let a: u8 = items[0];
let a: u8 = *items.index(&0); // Equivalent of above
let b: &u8 = &items[0];
let b: &u8 = &*items.index(&0); // Equivalent of above
Run Code Online (Sandbox Code Playgroud)
请注意,索引值也是通过引用自动获取的,类似于自动解除引用.
不,你正在做的一切正确.虽然index()方法确实返回引用,但在索引操作中调用它时,其结果会自动解除引用.这样做是为了使索引更自然:在存在某种索引操作符的每种语言中(主要是C和C++),它本身返回值,而不是对容器的引用.
为了获得对集合的引用,您必须明确地应用引用运算符(如在第一个"变通方法"中)或使用引用模式(如第二个).