如何将一个Vec传递给Rust中的多个函数?

时间:2017-03-22 14:06:59

标签: rust

我写了一个max函数,它以Vec为参数。它按我的预期工作。然后我添加了一个与min函数相同的max函数:

fn main() {
    let my_array = vec![61, 14, 71, 23, 42, 8, 13, 66];
    let max = max(my_array);
    let min = min(my_array);
    println!("Max value is {}.", max);
}

fn max(array: Vec<i32>) -> i32 {
    let mut max = array[0];
    for val in array {
        if max < val {
            max = val;
        }
    }
    max
}

fn min(array: Vec<i32>) -> i32 {
    let mut min = array[0];
    for val in array{
        if min > val {
            min = val;
        }
    }
    min
}
如果我在调用my_array时输入相同的min参数,

Rust会报错:

error[E0382]: use of moved value: `my_array`
 --> src/main.rs:4:19
  |
3 |     let max = max(my_array);
  |                   -------- value moved here
4 |     let min = min(my_array);
  |                   ^^^^^^^^ value used here after move
  |
  = note: move occurs because `my_array` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait

如何编写有效的代码?

1 个答案:

答案 0 :(得分:10)

这是Rust的初学者将遇到的问题。作为初学者,您应该阅读The Rust Programming Language。本书付出了很多努力,尤其是Rust的新手。这将涵盖您将遇到的许多事情。

相关部分:

潜在的问题是,当您致电max时,您已转移了向量的所有权。然后价值消失了; main不再拥有它。

最简单的方法是在传递给max之前克隆向量。这样,main可以保留my_array的所有权,然后在后续行中将所有权转移到min

let max = max(my_array.clone());
let min = min(my_array);

这是低效的,因为maxmin都不需要对向量进行所有权来完成工作。克隆Vec还需要额外的内存分配。传递切片更为惯用,切片Vec内部数据的一种引用:

let max = max(&my_array);
let min = min(&my_array);

// ...

fn max(array: &[i32]) -> i32 {
    let mut max = array[0];
    for &val in array {
        if max < val {
            max = val;
        }
    }
    max
}

在切片上进行迭代时,您将获得对切片中项目的引用。对于整数,我们可以取消引用它们(这里使用&中的for &val in array)并复制该值。

更好的是,没有必要重写这样的基本功能。您还假设始终至少有一个值,对于空向量,情况并非如此。惯用的解决方案是使用iterators

fn main() {
    let my_array = vec![61, 14, 71, 23, 42, 8, 13, 66];
    let max = my_array.iter().max();
    let min = my_array.iter().min();
    println!("Max value is {:?}.", max);
    println!("Min value is {:?}.", min);
}

这使用Iterator::minIterator::max,  每个返回Option,作为空切片没有最小值或最大值。

从技术上讲,它与原始解决方案略有不同,因为minmaxOption<&i32>;对原始切片的引用。您可以使用Option::cloned

返回Option<i32>
fn main() {
    let my_array = vec![61, 14, 71, 23, 42, 8, 13, 66];
    let max = my_array.iter().max().cloned();
    let min = my_array.iter().min().cloned();
    println!("Max value is {:?}.", max);
    println!("Min value is {:?}.", min);
}

奖励信息:切片,Vec和数组都是不同的类型。将my_array称为数组是不正确的。