首页 文章

索引Box错误的Vec

提问于
浏览
4

我正在玩 Vec 结构并遇到一些我无法理解的有趣错误和行为 . 考虑following code .

fn main() {
    let v = vec![box 1i];
    let f = v[0];
}

在Rust围栏中进行评估时,代码会产生以下错误:

<anon>:3:13: 3:17 error: cannot move out of dereference (dereference is implicit, due to indexing)
<anon>:3     let f = v[0];
                     ^~~~
<anon>:3:9: 3:10 note: attempting to move value to here (to prevent the move, use `ref f` or `ref mut f` to capture value by reference)
<anon>:3     let f = v[0];
                 ^
error: aborting due to previous error
playpen: application terminated with error code 101
Program ended.

我对 Vecindex方法的理解是,它返回对 Vec 中值的引用,所以我不明白发生了什么动作或隐式解引用 .

此外,当我change the f variable to an underscore,如下所示,没有错误产生!

fn main() {
    let v = vec![box 1i];
    let _ = v[0];
}

我希望有人可以解释我得到的错误,以及为什么他们在将 f 切换到 _ 时会消失 .

3 回答

  • 2

    不知道糖 v[0] 实现了哪种语法,但它试图移动值而不是获取引用 .

    但是如果你调用 .index() ,它可以工作并为你提供一个与向量相同生命周期的引用:

    fn main() {
        let v = vec![box 1i];
        let f = v.index(&0);
        println!("{}", f);
    }
    

    第二个示例有效,因为当值被丢弃时,它不会尝试移动它 .

    编辑:

    v[0] 的desugar是 *v.index(&0) (来自:https://github.com/rust-lang/rust/blob/fb72c4767fa423649feeb197b50385c1fa0a6fd5/src/librustc/middle/trans/expr.rs#L467) .

    fn main() { 
        let a = vec!(1i);
        let b = a[0] == *a.index(&0);
        println!("{}" , b);
    }
    
    true
    
  • 1

    在您的代码中, let f = v[0]; 按值分配f(如错误消息中所述,它隐式解除引用):编译器尝试将 v[0] 复制或移动到 f 中 . v[0]box ,它无法复制,因此它应该像这种情况一样移动:

    let a = box 1i;
    let b = a;
    // a cannot be used anymore, it has been moved
    // following line would not compile
    println!("{}", a);
    

    但是值不能通过索引从向量中移出,因为它是返回的引用 .

    关于 _ ,这段代码:

    fn main() {
        let v = vec![box 1i];
        let _ = v[0];
        println!("{}", _);
    }
    

    产生此错误:

    <anon>:4:20: 4:21 error: unexpected token: `_`
    <anon>:4     println!("{}", _);
                                ^
    

    _ 不是变量名,而是锈的特殊名称,告诉你不要试图复制或移动任何东西 .

  • 1

    您可以通过取消引用v [0]来使原始功能起作用:

    fn main() {
        let v = vec![box 1i];
        let f = &v[0]; // notice the &
        println!("{}",f);
    }
    

    我不知道为什么下划线会使你的错误无声无息 . 它应该引发错误,因为仅下划线是一个无效的变量名称(我认为) . 试图打印它会产生错误:

    fn main() {
        let v = vec![box 1i];
        let _ = &v[0];
        println!("{}",_);
    }
    

    输出:

    <anon>:4:19: 4:20 error: unexpected token: `_`
    <anon>:4     println!("{}",_);
    

    下划线用于静默未使用的变量警告(例如,如果您定义 some_var 并且从不使用它,编译器将对您大喊大叫,但如果您定义 _some_var 并且从不使用它则不会 . )它还用作匹配语句中的后备,以匹配与其他路径不匹配的任何内容:

    fn main() {
        let v = vec![box 1i];
        let f = &v[0];
        match **f {
            3i => println!("{}",f),
            _ => println!("nothing here")
        };
    }
    

    比我聪明的人应评论下划线是否是有效的变量名称 . 老实说,我认为编译器不应该允许它 .

相关问题