即使使用cloned()也使用移动值错误

时间:2015-06-30 23:57:37

标签: rust

我试图找出为什么我收到有关此代码段的移动值的错误:

fn get_names(v: Vec<(String, usize)>) -> Vec<String> {
    v.iter().cloned()
        .map(|(name, _value)| name)
        .collect()
}

fn main() {
    let v = vec!(("Herman".to_string(), 5));
    println!("running");
    let names = get_names(v);

    assert_eq!(names, ["Herman"]);
    println!("{:?}", v);
}

我正在阅读this每周生锈文章,并注意到此代码块

fn get_names(v: Vec<(String, usize)>) -> Vec<String> {
    v.into_iter()
        .map(|(name, _score)| name)
        .collect()
}

fn main() {
    let v = vec!( ("Herman".to_string(), 5));
    let names = get_names(v);

    assert_eq!(names, ["Herman"]);
}

语法对我有意义,但为什么有人想要移出一个向量并使v无效?为什么你不只是创建一个向量names而不是从v窃取?我尝试修改程序只复制名称但我得到错误:

src/main.rs:13:22: 13:23 error: use of moved value: `v`
src/main.rs:13     println!("{:?}", v);
                                    ^
note: in expansion of format_args!
<std macros>:2:25: 2:56 note: expansion site
<std macros>:1:1: 2:62 note: in expansion of print!
<std macros>:3:1: 3:54 note: expansion site
<std macros>:1:1: 3:58 note: in expansion of println!
src/main.rs:13:5: 13:25 note: expansion site
src/main.rs:10:27: 10:28 note: `v` moved here because it has type `collections::vec::Vec<(collections::string::String, usize)>`, which is non-copyable
src/main.rs:10     let names = get_names(v);
                                         ^
error: aborting due to previous error
Could not compile `tutorial`.

1 个答案:

答案 0 :(得分:4)

主要问题是你没有改变函数的参数来接收指向原始向量的指针,所以它仍然将它作为移动值显示出来。所以改变这一行:

fn get_names(v: Vec<(String, usize)>) -> Vec<String>

进入这一个:

fn get_names(v: &Vec<(String, usize)>) -> Vec<String>

您必须相应地更改通话:get_names(&v);

此外,不是在克隆整个元组的迭代器中使用cloned(),而是可以遍历指针并仅克隆字符串。在这种情况下不会有太大的区别,但如果向量中的对象更复杂,那么它可能很重要。像这样:

fn get_names(v: &Vec<(String, usize)>) -> Vec<String> {
    v.iter()
        .map(|&(ref name, _value)| name.clone())
        .collect()
}

不要忘记{tag}表达式中的ref,因为您无法取得v的借用成员的所有权。并且不要忘记&因为你正在迭代一个指针,所以你得到了指向元组的指针。

另请注意,您可以使用原始get_names()函数而不会使向量无效。只需写下get_names(v.clone())