如何正确返回对临时值的引用?

How to correctly return a reference to temporary value?

提问人:Kodra 提问时间:10/12/2023 更新时间:10/12/2023 访问量:56

问:

例如,此函数按预期工作:

fn get_suffix(str: Option<&str>) -> u32 {
    str.and_then( |s| s.rsplit('_').next() )
       .and_then( |s| s.parse::<u32>().ok() )
       .unwrap_or(0)
}

但这给了我编译错误:

fn get_suffix_from_path(path: &Path) -> u32 {
    path.file_stem()
        .and_then( |s| s.to_string_lossy().rsplit('_').next() )
        .and_then( |s| s.parse::<u32>().ok() )
        .unwrap_or(0)
}
328 |                     stem.to_string_lossy().rsplit('_').next())
    |                     ----------------------^^^^^^^^^^^^^^^^^^^
    |                     |
    |                     returns a value referencing data owned by the current function
    |                     temporary value created here

我不完全确定这意味着什么。它是否是由关闭结束时会立即丢弃的事实造成的?解决这个问题的惯用方法是什么?to_string_lossy()String

我试过了这个:

stem.to_string_lossy().rsplit('_').next().and_then(|s| Some(s.to_owned()) )

它有效,但它不仅丑陋,而且不必要地复制了字符串。

Rust Closures 借用检查器

评论


答:

2赞 prog-fh 10/12/2023 #1

你是对的:在你解析其内容并获得整数之前,提供的必须存在。Cow<str>.to_string_lossy()

您只需要在存在此漏洞的闭包内执行解析即可。Cow<str>

use std::path::Path;

fn get_suffix_from_path(path: &Path) -> u32 {
    path.file_stem()
        .and_then(|s| {
            s.to_string_lossy()
                .rsplit('_')
                .next()
                .and_then(|s| s.parse().ok())
        })
        .unwrap_or(0)
}

fn main() {
    let p = Path::new("/tmp_56");
    let s = get_suffix_from_path(&p);
    println!("{:?} {:?}", p, s);
}
/*
"/tmp_56" 56
*/
0赞 Rasmus Kaj 10/12/2023 #2

你是对的,在你的示例中,“额外”副本实际上是必需的(你可以字符串化和修改to_string_lossy返回的 Cow,使其只有一个副本,而不是两个副本)。

如果奶牛是借来的或拥有的,你也可以打开,并归还一头奶牛,该奶牛要么是子借用的,要么是对拥有的字符串的修改。但这变得相当复杂。

在大多数情况下,您也可以选择仅支持 utf-8 路径,并使用 path.to_str(),然后将其解包(在非 utf8 路径上引起恐慌)或以其他方式将其作为错误处理。