Rust函数的返回值不能引用局部或临时变量

vc9ivgsu  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(138)

上下文

我相信我明白这些错误试图告诉我什么,但我不明白我是如何提交错误/如何解决它们的。
该函数是一个递归函数,它遍历一个目录及其子目录,并累积一个路径向量和一个Axum方法路由器(我不相信这与我面临的实际问题有任何关系)。

错误

编译器错误状态“无法返回引用局部变量path的值”。
如果将path.to_str()替换为path.clone().to_str(),则错误变为“无法返回引用临时值的值”。

代码

fn assign_handlers(dir: Option<&str>) -> Vec<(&str, MethodRouter)> {
    //Check root dir validity
    let dir = match dir {
        Some(s) => s,
        None => return vec![],
    };

    //Look for routes in dir
    let dir_path = fs::read_dir(dir).expect(&format!("Unable to access directory '{}'", &dir));
    let mut routes = Vec::new();
    for entry in dir_path {
        match entry {
            Ok(entry) => {
                let path = entry.path();
                if path.is_dir() {
                    //Recurse into subdirectories
                    let subroutes = assign_handlers(path.to_str());
                    for route in subroutes {
                        routes.push(route)
                    }
                } else if path.is_file() {
                    // Cut for brevity (and because I don't know what goes here yet)
                }
            },
            Err(_) => {},
        }
    }

    routes
}

字符串

dauxcl2d

dauxcl2d1#

Rust是正确的。让我们解码&str&表示它是一个引用,str表示它是一个字符串的内容。在垃圾收集语言中,引用使对象保持活动状态,这很方便,但Rust做出了不同的选择,这通常更快,更节省内存,这可以用来发现编译器在其他语言中会忽略的许多错误:引用不能使对象保持活动状态。
这就是编译器告诉你的:一个 temporary 值,根据定义,一旦你离开代码块,它就不再存在了。因为你在函数中指定的返回类型包含&str,编译器信任你,并假设subroutes包含临时值,并且你试图返回它们。因为你不能返回临时值,所以你得到了一个错误。
所以,你应该做的是返回一个保证保持活动的东西。例如,这可能是一个String。除了,在这种情况下,你已经有了一个活动的东西:一个PathBuf-这相当于一个String,除了它使用你的文件系统的编码,根据操作系统的要求(许多语言混淆了PathBufString-这使得大多数用这些语言编写的应用程序在日本,韩国或中国无法使用,例如)。
通过这些更改,您可以获得:

fn assign_handlers(dir: Option<&Path>) -> Vec<(PathBuf, MethodRouter)> {
    //Check root dir validity
    let dir = match dir {
        Some(s) => s,
        None => return vec![],
    };

    //Look for routes in dir
    let dir_path = fs::read_dir(dir).expect(&format!("Unable to access directory '{:?}'", &dir));
    let mut routes = Vec::new();
    for entry in dir_path {
        match entry {
            Ok(entry) => {
                let path = entry.path();
                if path.is_dir() {
                    //Recurse into subdirectories
                    let subroutes = assign_handlers(Some(&path));
                    for route in subroutes {
                        routes.push(route)
                    }
                } else if path.is_file() {

                }
            },
            Err(_) => {},
        }
    }

    routes
}

字符串
另外,我不确定为什么要传递Option<&PathBuf>。我建议只传递&PathBuf。这样可以简化代码。

相关问题