索引操作的 return 类型是什么?
What is the return type of the indexing operation?
我正在尝试使用切片,但很不成功。
我已将我的第一期缩减为:
fn at<'a, T>(slice: &'a [T], index: usize) -> &'a T {
let item = slice[index];
item
}
鉴于 documentation:
,我希望 slice[index]
的 return 类型可以作为参考
pub trait Index<Index> {
type Output;
fn index(&'a self, index: &Index) -> &'a <Self as Index<Index>>::Output;
// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
但是,编译器给我一个错误:
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
的类型与函数的 return 类型不匹配(我引入 item
只是为了调试目的,将表达式求值从return).
如果我将 return 类型切换为 T
,这是 item
的类型,我会收到另一条错误消息:
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
}
强制类型成为引用就可以了。
为什么首先需要这些恶作剧?我做错了什么吗?
不,您做的一切都正确。虽然 index()
方法执行 return 引用,但在索引操作中调用它时,其结果会自动取消引用。这样做是为了使索引更自然:在存在某种索引运算符的每种语言中(主要是 C 和 C++),它 return 值本身,而不是对容器的引用。
为了获得对集合的引用,您必须显式应用引用运算符(如在第一个 "workaround" 中)或使用引用模式(如在第二个中)。
这是编译器为您所做的一些有用的人体工程学,目的是使代码看起来更漂亮。
Index
特征 的 return 值是 一个引用,但是编译器会自动为你插入一个取消引用 当你使用加糖语法 []
。大多数其他语言只会 return 数组中的项目(复制它或 return 对该对象的另一个引用,只要合适)。
由于 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
请注意,索引值也会通过引用自动获取,类似于自动取消引用。
我正在尝试使用切片,但很不成功。
我已将我的第一期缩减为:
fn at<'a, T>(slice: &'a [T], index: usize) -> &'a T {
let item = slice[index];
item
}
鉴于 documentation:
,我希望slice[index]
的 return 类型可以作为参考
pub trait Index<Index> {
type Output;
fn index(&'a self, index: &Index) -> &'a <Self as Index<Index>>::Output;
// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
但是,编译器给我一个错误:
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
的类型与函数的 return 类型不匹配(我引入 item
只是为了调试目的,将表达式求值从return).
如果我将 return 类型切换为 T
,这是 item
的类型,我会收到另一条错误消息:
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
}
强制类型成为引用就可以了。
为什么首先需要这些恶作剧?我做错了什么吗?
不,您做的一切都正确。虽然 index()
方法执行 return 引用,但在索引操作中调用它时,其结果会自动取消引用。这样做是为了使索引更自然:在存在某种索引运算符的每种语言中(主要是 C 和 C++),它 return 值本身,而不是对容器的引用。
为了获得对集合的引用,您必须显式应用引用运算符(如在第一个 "workaround" 中)或使用引用模式(如在第二个中)。
这是编译器为您所做的一些有用的人体工程学,目的是使代码看起来更漂亮。
Index
特征 的 return 值是 一个引用,但是编译器会自动为你插入一个取消引用 当你使用加糖语法 []
。大多数其他语言只会 return 数组中的项目(复制它或 return 对该对象的另一个引用,只要合适)。
由于 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
请注意,索引值也会通过引用自动获取,类似于自动取消引用。