为什么迭代i32的向量会引用i32(& i32)? [英] Why does iterating a vector of i32s give references to i32 (&i32)?

查看:65
本文介绍了为什么迭代i32的向量会引用i32(& i32)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下程序尝试对学生的成绩进行评分:

The following program tries to grade the marks of a student:

use std::io;

fn main() {
    let mut in0 = String::new();
    io::stdin().read_line(&mut in0).expect("stdin err");
    let n: i32 = in0.trim().parse().expect("parse err");
    println!("{}", n);
    let mut v: Vec<i32> = Vec::new();
    for _ in 0..n {
        let mut inp = String::new();
        io::stdin().read_line(&mut inp).expect("stdin err");
        let num: i32 = inp.trim().parse().unwrap();
        v.push(num);
    }
    let out: Vec<_> = v
        .iter()
        .map(|x| {
            if x < 38 {
                x
            } else if x % 5 > 3 {
                x + x % 5
            } else {
                x
            }
        })
        .collect();
    println!("{:?}", v);
}

在编译时,出现以下错误.

While compiling, I get the following error.

error[E0308]: mismatched types
  --> src/main.rs:19:20
   |
19 |             if x < 38 {
   |                    ^^
   |                    |
   |                    expected `&i32`, found integer
   |                    help: consider borrowing here: `&38`

error[E0308]: `if` and `else` have incompatible types
  --> src/main.rs:24:17
   |
21 |               } else if x % 5 > 3 {
   |  ____________________-
22 | |                 x + x % 5
   | |                 --------- expected because of this
23 | |             } else {
24 | |                 x
   | |                 ^ expected `i32`, found `&i32`
25 | |             }
   | |_____________- `if` and `else` have incompatible types
   |
help: consider dereferencing the borrow
   |
23 |             } else *{
24 |                 x
25 |             }

x 变量是& i32 类型而不是 i32 类型吗?

How is the x variable a &i32 type and not a i32 type?

推荐答案

调用 .iter() 方法在引用向量的元素时返回一个迭代器.否则,将不得不将元素移出或复制出向量,这在一般情况下 [1] 是不希望的.在文档中,从声明中并不能立即看出这一点:

Calling the .iter() method on a vector returns an iterator over references the vector's elements. Otherwise, it would have to move or copy the elements out of the vector, which is not desirable in the general case [1]. In the documentation this is not immediately obvious from the declaration:

pub fn iter(&self) -> Iter<T>  // Return type does not look like a reference

但是,示例显示您获得了参考:

However, the examples show that you get a reference:

assert_eq!(iterator.next(), Some(&1));  // note the `&1` instead of just `1`

可以指示闭包取消引用参数:

The closure can be instructed to dereference the parameter:

v.iter().map(|&x| { /* do something */ })

如果向量包含 Copy able类型(例如 i32 ),这很好.否则,这将导致无法移出借用的内容错误.在这种情况下,您可能还是要使用参考.

This is fine if the vector contains Copyable types like i32. Otherwise this would result in a cannot move out of borrowed content error. In this case you will likely want to work with a reference anyway.

如果迭代后不再需要该向量,则可以使用 .into_iter(),它会消耗该向量并遍历所拥有的项目而不是引用.

If you no longer need the vector after iterating you can use .into_iter(), which consumes the vector and iterates over owned items instead of references.

[1]移动会清除向量,该向量已被 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆