Rust中如何从字符串创建字符串切片

5
"切片是一种引用类型,因此它没有所有权。"
以下代码简化了操作,使用了一个匹配表达式(match)返回一个切片(slice),除了一种情况,其他情况返回了一个字符串切片。在一个情况下需要在切片周围添加单引号,因此我们使用返回一个字符串(String)的'format!'函数。然后将String转换为'&str'。
错误显示匹配表达式中的临时String引用了结果切片。
11 |     ret
   |     ^^^ returns a value referencing data owned by the current function

以下是简化后的代码。请注意,我们不是使用字面值,而是从第三方包返回的 &str
fn my_func(input: &str) ->&str {
    
    let ret =
        match input {
            "a" => "Apha", // in fact, a &str from a crate
            _ => format!("'{}'", "Quoted" ).as_str(), 
        };
        
    ret
}
 

&str 是期望的类型,因为这样可使用 push_str() 推送字符串。

fn main() {
    let mut s = String::new();
    s.push_str(my_func("a"));
    
...

您在match中是建议复制str还是解引用临时字符串?

3个回答

6

您不能返回对本地分配的String的引用,因为当函数返回时,该字符串将被删除。没有办法绕过这个问题。 &str类型的数据与您要返回的数据类型根本不匹配。

最简单的解决方法是返回一个拥有的String

fn my_func(input: &str) -> String {
    match input {
        "a" => "Alpha".to_string(),
        _ => format!("'{}'", "Quoted" ), 
    }
}

另一种方法是返回一个 Cow<'_, str>,它可以根据你拥有的是借用字符串还是拥有字符串来进行持有。这有点繁琐,但它避免了不必要的分配。我只建议在效率至关重要时使用此方法;否则,只需返回String

fn my_func(input: &str) -> Cow<'_, str> {
    match input {
        "a" => "Alpha".into(),
        _ => format!("'{}'", "Quoted" ).into(), 
    }
}

我还会提到第三个选项——仅供教育目的,不是实际使用,因为它会泄露内存。如果你泄漏了一个对象,你可以得到一个指向拥有对象的静态引用。由于泄漏的内存从未被释放,所以在程序的剩余时间内内存是有效的,因此您实际上可以获得对它的引用。
// Warning: Do not use! Leaks memory.
fn my_func(input: &str) -> &'static str {
    match input {
        "a" => "Alpha",
        _ => Box::leak(format!("'{}'", "Quoted").into_boxed_str()), 
    }
}

字符串,我本来想避免的。Cow它可能会被使用;感谢指引。那个`_是未使用的生命周期吗? - A Boston
1
“_” 告诉编译器推断生命周期。它使用 input: &str 中的匿名生命周期 - 如果我写成 input: &'a str,那么类型将是 Cow<'a, str>。如果您不想将输出生命周期绑定到输入字符串,则可以将其更改为 Cow<'static, str> - John Kugelman

1
除了其他的答案,您还可以更改my_func以接受一个参数,该参数告诉它将结果放在哪里,而不是返回它。
use std::fmt::Write;

fn my_func(output: &mut impl Write, input: &str) {
    match input {
        "a" => write!(output, "Apha").unwrap(), // in fact, a &str from a crate
        _ => write!(output, "'{}'", "Quoted" ).unwrap(), 
    };
}

fn main() {
    let mut s = String::new();
    my_func(&mut s, "a");
}

游乐场


1
问题在于带有 format!().as_str() 的参数生成了一个拥有所有权的 String,一旦您的函数返回,该 String 将被丢弃,&str 引用将变得无效。
您可以使用 std::borrow::Cow 允许函数返回拥有或借用的字符串。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接