代码之家  ›  专栏  ›  技术社区  ›  Bibek Shah

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

  •  3
  • Bibek Shah  · 技术社区  · 7 年前

    以下程序尝试为学生评分:

    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);
    }
    

    编译时,出现以下错误。

    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 变量a &i32 类型而非a i32 类型

    2 回复  |  直到 5 年前
        1
  •  5
  •   MB-F    5 年前

    调用 .iter() 方法返回引用向量元素的迭代器。否则,它将不得不将元素移出或复制出向量,这在一般情况下是不可取的 [1] . 在文件中,这一点从声明中并不明显:

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

    但是,示例显示您得到了一个参考:

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

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

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

    如果向量包含 Copy 有能力的类型,如 i32 . 否则会导致 无法移出借用的内容 错误在这种情况下,您可能无论如何都希望使用引用。

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

    [1] 移动将清除向量,该向量由 .drain() 方法,并且无法对所有类型进行复制/高效复制。

        2
  •  2
  •   Boiethios    7 年前

    如果您想消费 Vec ,您必须使用 into_iter() 方法:

    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.into_iter().map(|x| {
            if x < 38 {
                x
            } else if x % 5 > 3 {
                x + x % 5
            } else {
                x
            }
        }).collect();
        println!("{:?}", out);
    }
    

    如果不使用向量,那么向量中的东西只能借用,不能移动。

    推荐文章