为什么迭代 i32 的向量会引用 i32 (&i32)?

Bib*_*hah 3 mapping reference vector rust

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

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);
}
Run Code Online (Sandbox Code Playgroud)

编译时,我收到以下错误。

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);
}
Run Code Online (Sandbox Code Playgroud)

x变量如何是&i32类型而不是i32类型?

kaz*_*ase 5

.iter()在向量上调用该方法会返回一个迭代器,该迭代器引用了该向量的元素。否则,它必须从向量中移动或复制元素,这在一般情况下是不可取的[1]。在文档中,这从声明中并不明显:

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

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

assert_eq!(iterator.next(), Some(&1));  // note the `&1` instead of just `1`
Run Code Online (Sandbox Code Playgroud)

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

v.iter().map(|&x| { /* do something */ })
Run Code Online (Sandbox Code Playgroud)

如果向量包含Copyi32. 否则这将导致无法移出借用内容错误。在这种情况下,您可能无论如何都希望使用参考。

如果迭代后不再需要向量,则可以使用.into_iter(),它使用向量并迭代拥有的项目而不是引用。

[1] 移动会清除该.drain()方法覆盖的向量,并且复制在所有类型上都是不可能/高效的。