我试图找出为什么我收到有关此代码段的移动值的错误:
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`.
答案 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())
!