【问题标题】:What is the return type of the indexing operation?索引操作的返回类型是什么?
【发布时间】:2015-03-08 20:55:29
【问题描述】:

我正在尝试玩切片,但非常不成功。

我已将我的第一个问题简化为:

fn at<'a, T>(slice: &'a [T], index: usize) -> &'a T {
    let item = slice[index];
    item
}

鉴于documentation,我希望slice[index] 的返回类型是一个参考:

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 的类型与函数的返回类型不匹配(我引入item 仅出于调试目的,将表达式评估与返回分开)。

如果我将返回类型切换为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
}

强制类型为引用就可以了。

为什么首先需要这些恶作剧?我做错了什么吗?

【问题讨论】:

    标签: rust


    【解决方案1】:

    这是编译器为您所做的一些有用的人体工程学设计,以使代码看起来更漂亮。

    Index trait 的返回值一个引用,但编译器会自动为你插入一个解引用当你使用加糖语法时[]。大多数其他语言只会从数组中返回项目(复制它或返回对该对象的另一个引用,只要合适)。

    由于 Rust 对移动/复制语义的重要性,您不能总是将复制作为值,因此在这些情况下,您通常会使用 &amp;

    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
    

    请注意,索引值也是通过引用自动获取的,类似于自动取消引用。

    【讨论】:

    • 啊!我明白了,所以我被[]的糖抓住了!我没有想过直接调用index,因为我没想到会有区别,即使我已经注意到用T 调用[] 会降低使用&amp;T 调用index 的区别。感谢您的插图,它确实有助于将事物可视化。
    【解决方案2】:

    不,你做的一切都是正确的。虽然index() 方法确实返回一个引用,但在索引操作中调用它时,它的结果会自动取消引用。这样做是为了使索引更自然:在存在某种索引运算符的每种语言中(主要是 C 和 C++),它返回值本身,而不是容器的引用。

    为了获得对集合的引用,您必须明确应用引用运算符(如在您的第一个“解决方法”中)或使用引用模式(如在第二个中)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-06
      • 1970-01-01
      • 2018-09-04
      • 1970-01-01
      • 2018-04-04
      • 2018-01-17
      • 1970-01-01
      相关资源
      最近更新 更多