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

9vw9lbht  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(129)

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

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,当闭包结束时,String会立即被丢弃吗?解决这个问题的惯用方法是什么?
我试过这个:

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

它可以工作,但它不仅很丑,而且不必要地复制了字符串。

pb3s4cty

pb3s4cty1#

你说得对:由.to_string_lossy()提供的Cow<str>必须存在,直到您解析其内容并获得整数。
您只需在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
*/
kse8i1jr

kse8i1jr2#

你是对的,在你的例子中,“额外的”副本实际上是必要的(你可以对to_string_lossy返回的Cow进行字符串化和 * 修改 *,使其只有一个副本,而不是可能的两个)。
如果cow是借用的或拥有的,您也可以打开,并返回一个cow,该cow是子借用或拥有字符串的修改。但这变得相当复杂。
在大多数情况下,您也可以选择只支持utf-8路径,并使用path.to_str(),然后将其解包(在非utf 8路径上导致死机)或以其他方式将其作为错误处理。

相关问题