Vector 使用不可复制的移动值[E0382][E0277]
我有一个所有权问题,我不太明白。基本上,我尝试在我的文件系统上创建一些硬链接,并在创建后删除它们。因此,我创建了一系列整数,这些整数映射到我想要创建和销毁的实际文件名。我的天真解决方案如下所示:Vector 使用不可复制的移动值[E0382][E0277],vector,iterator,rust,clone,ownership,Vector,Iterator,Rust,Clone,Ownership,我有一个所有权问题,我不太明白。基本上,我尝试在我的文件系统上创建一些硬链接,并在创建后删除它们。因此,我创建了一系列整数,这些整数映射到我想要创建和销毁的实际文件名。我的天真解决方案如下所示: use std::fs; const src_file: &'static str = "a.txt"; const file_ext: &'static str = ".txt"; fn create_hardlink(dest_file: &str) { fs::
use std::fs;
const src_file: &'static str = "a.txt";
const file_ext: &'static str = ".txt";
fn create_hardlink(dest_file: &str) {
fs::hard_link(&src_file, &dest_file);
}
fn main() {
let create = (0..10000).map(|x| x.to_string() + file_ext);
let remove = (0..10000).map(|x| x.to_string() + file_ext);
for file in create {
create_hardlink(&file);
}
for file in remove {
fs::remove_file(&file);
}
}
但我实际上想要实现的是一个解决方案,在这个解决方案中,我不必重复我自己创建带有文件名的静态集合,并且可以在一秒钟内重复使用文件
:
...
fn main() {
let files = (0..10000).map(|x| x.to_string() + file_ext);
for file in files {
create_hardlink(&file);
}
for file in files {
fs::remove_file(&file);
}
}
所以当我尝试这个方法时,编译器抱怨说,文件的第二次使用是不可能的
src/main.rs:20:17: 20:22 error: use of moved value: `files` [E0382]
src/main.rs:20 for file in files {
因为文件
已移动到第一个for循环中:
src/main.rs:16:17: 16:22 note: `files` moved here because it has type `core::iter::Map<core::ops::Range<i32>, [closure@src/main.rs:14:36: 14:64]>`, which is non-copyable
但这并不像我期望的那样有效:
src/main.rs:16:5: 18:6 error: the trait `core::iter::Iterator` is not implemented for the type `alloc::rc::Rc<core::cell::RefCell<core::iter::Map<core::ops::Range<_>, [closure@src/main.rs:14:53: 14:81]>>>` [E0277]
src/main.rs:16 for file in files.clone() {
src/main.rs:17 create_hardlink(&file);
src/main.rs:18 }
note: in expansion of for loop expansion
src/main.rs:16:5: 18:6 note: expansion site
src/main.rs:16:5: 18:6 help: run `rustc --explain E0277` to see a detailed explanation
src/main.rs:16:5: 18:6 note: `alloc::rc::Rc<core::cell::RefCell<core::iter::Map<core::ops::Range<_>, [closure@src/main.rs:14:53: 14:81]>>>` is not an iterator; maybe try calling `.iter()` or a similar method
src/main.rs:16 for file in files.clone() {
src/main.rs:17 create_hardlink(&file);
src/main.rs:18 }
note: in expansion of for loop expansion
src/main.rs:16:5: 18:6 note: expansion site
src/main.rs:16:5: 18:6 note: required by `core::iter::IntoIterator::into_iter`
src/main.rs:16 for file in files.clone() {
src/main.rs:17 create_hardlink(&file);
src/main.rs:18 }
src/main.rs:16:5:18:6错误:未为类型'alloc::rc::rc`[E0277]实现特性'core::iter::Iterator'
src/main.rs:16用于files.clone()中的文件{
src/main.rs:17创建硬链接(&file);
src/main.rs:18}
注:在循环扩展的扩展中
src/main.rs:16:5:18:6注:扩建场地
src/main.rs:16:5:18:6帮助:运行'rustc--explain E0277'查看详细说明
src/main.rs:16:5:18:6注意:`alloc::rc::rc`不是迭代器;也许可以尝试调用“.iter()”或类似的方法
src/main.rs:16用于files.clone()中的文件{
src/main.rs:17创建硬链接(&file);
src/main.rs:18}
注:在循环扩展的扩展中
src/main.rs:16:5:18:6注:扩建场地
src/main.rs:16:5:18:6注:由'core::iter::IntoIterator::intoiter'所需`
src/main.rs:16用于files.clone()中的文件{
src/main.rs:17创建硬链接(&file);
src/main.rs:18}
我能做什么?我真的必须为类型alloc::rc::rc实现core::iter::Iterator
,据我所知,Rust迭代器只是前向迭代器,因此只能迭代一次。您可以将它们收集到向量中,或使用函数生成迭代器:
//第一个选项
let files:Vec=(0..10000).map(|x | x.to_string()+file_ext).collect();
对于f-in&files{…}//Borrow`files`
//第二种选择
让files=| |(0..10000).map(| x | x.to_string()+file_ext);
对于文件中的f(){…}//调用闭包以获取迭代器
这里有几个问题
第一个是电话
for f in files { ... }
将按值获取文件
。这可以通过引用来避免:
for f in &files { ... }
因为(&foo).into_iter()
有效地解析为foo.iter()
第二个是文件
必须是mut
,如果要迭代迭代器,则引用&mut
。如果您有一些向量,那么迭代和my_vector
是有意义的-您可以在不修改它的情况下迭代它。但是,如果您有一个迭代器本身,那么状态将在迭代器本身中保留和更新
let mut files = (0..10000).map(|x| x.to_string() + file_ext);
for file in &mut files {
create_hardlink(&file);
}
for file in files {
fs::remove_file(&file);
}
第三,即使您做了这些事情,因为您使用的是单个迭代器,所以每个元素只能迭代一次!第二个循环将为空。这就是@filmor提供的解决方案的问题。我认为第一种选择是惯用的解决方案。第二个选项将导致额外的10000个分配,因为该范围将运行两次。但是第一个选项将一次分配所有内存,这取决于文件的数量,这可能也不是很好。感谢您的解决方案和评论!创建一个宏以避免像这样的选项2的双重分配是否是一种有价值的方法<代码>宏规则!files_vec{($range:expr)=>{$range.map(|x | x.to_string()+file_ext).collect()}
这是非常不灵活的,但预编译感谢您的解释!正如你所指出的,我的代码没有迭代器更有意义,因此我接受了@filmor的答案。
let mut files = (0..10000).map(|x| x.to_string() + file_ext);
for file in &mut files {
create_hardlink(&file);
}
for file in files {
fs::remove_file(&file);
}