你如何归还不可复制的类型?

Cal*_*zyk 6 function rust

我试图了解你如何返回非原语(即没有实现的类型Copy).如果返回类似a的内容i32,则该函数会在内存中创建一个带有返回值副本的新值,因此可以在函数范围之外使用它.但是如果您返回的类型没有实现Copy,则不会执行此操作,并且您将获得所有权错误.

我已经尝试使用Box在堆上创建值,以便调用者可以获取返回值的所有权,但这似乎也不起作用.

也许我通过使用我在C#或其他语言中使用的相同编码样式以错误的方式接近它,其中函数返回值,而不是将对象引用作为参数传递并对其进行变更,以便您可以轻松指示所有权在Rust.

以下代码示例无法编译.我相信问题只在迭代器闭包内,但我已经包含了整个函数,以防万一我没有看到.

pub fn get_files(path: &Path) -> Vec<&Path> { 
      let contents = fs::walk_dir(path); 

      match contents { 
          Ok(c) => c.filter_map(|i| { match i { 
                  Ok(d) => {  
                      let val = d.path(); 
                      let p = val.as_path(); 
                      Some(p) 
                  }, 
                  Err(_) => None } }) 
              .collect(), 
          Err(e) => panic!("An error occurred getting files from {:?}: {}", pa
    th, e) 
      } 
 }
Run Code Online (Sandbox Code Playgroud)

编译器给出以下错误(我已删除所有行号和无关文本):

error: `val` does not live long enough
                     let p = val.as_path();
                                            ^~~
in expansion of closure expansion
expansion site
reference must be valid for the anonymous lifetime #1 defined on the block...
...but borrowed value is only valid for the block suffix following statement
                     let val = d.path();
                     let p = val.as_path();
                     Some(p)
                 },
Run Code Online (Sandbox Code Playgroud)

She*_*ter 8

你返回一个值... 返回它.但是,您的签名显示您正在尝试返回对值引用.当对象将在块的末尾被删除时,您不能这样做,因为引用将变为无效.

在你的情况下,我可能会写一些类似的东西

#![feature(fs_walk)]

use std::fs;
use std::path::{Path, PathBuf};

fn get_files(path: &Path) -> Vec<PathBuf> { 
    let contents = fs::walk_dir(path).unwrap(); 
    contents.filter_map(|i| {
        i.ok().map(|p| p.path())
    }).collect()
}

fn main() {
    for f in get_files(Path::new("/etc")) {
        println!("{:?}", f);
    }
}
Run Code Online (Sandbox Code Playgroud)

主要的是该函数返回一个Vec<PathBuf>- 拥有该路径的类型的集合,而不仅仅是对其他人的内存的引用.

在你的代码中,你做到了let p = val.as_path().在这里,val是一个PathBuf.然后你打电话as_path,定义为:fn as_path(&self) -> &Path.这意味着,给一个参考PathBuf,你可以得到一个参考Path ,只要将生活PathBuf的意愿.但是,您试图将该引用保持的时间比vec存在的时间长,因为它将在迭代结束时被删除.

  • 补充答案:`PathBuf`是`&Path`,`String`是`&str`.如果你掌握了`String` /`&str`二分法,这可能有助于你理解为什么在这里返回`PathBuf`是正确的. (5认同)