首页 文章

将本地String作为切片返回(&str)

提问于
浏览
31

有几个问题似乎与我遇到的问题有关 . 例如,请参见herehere . 基本上我正在尝试在本地函数中构建 String ,但随后将其作为 &str 返回 . 切片isn 't working because the lifetime is too short. I can' t直接在函数中使用 str ,因为我需要动态构建它 . 但是,我也不想返回 String ,因为它进入的对象的性质一旦构建就是静态的 . 有没有办法让我的蛋糕也吃?

这是一个最小的非编译复制:

fn return_str<'a>() -> &'a str {
    let mut string = "".to_string();

    for i in 0..10 {
        string.push_str("ACTG");
    }

    &string[..]
}

3 回答

  • 0

    您可以选择 leak memoryString 转换为 &'static str

    fn return_str() -> &'static str {
        let string = "ACTG".repeat(10);
    
        Box::leak(string.into_boxed_str())
    }
    

    在许多情况下,这是一个非常糟糕的主意,因为每次调用此函数时内存使用量将永远增长 .

    如果您希望每次调用都返回相同的字符串,请参阅:

  • 52

    不,你不能这样做 . 至少有两种解释为何如此 .

    首先,请记住引用是借用的,即它们指向某些数据但不拥有它,它由其他人拥有 . 在这种特殊情况下,字符串(您要返回的切片)由函数拥有,因为它存储在局部变量中 .

    当函数退出时,它的所有局部变量都被销毁;这涉及调用析构函数, String 的析构函数释放字符串使用的内存 . 但是,您希望返回指向为该字符串分配的数据的借用引用 . 这意味着返回的引用立即变为悬空 - 它指向无效的内存!

    除此之外,还创建了Rust,以防止出现此类问题 . 因此,在Rust中,不可能返回指向函数局部变量的引用,这在C语言中是可能的 .

    还有另一种解释,稍微更正式一些 . 我们来看看你的功能签名:

    fn return_str<'a>() -> &'a str
    

    请记住,生命周期和泛型参数都是参数:它们由函数的调用者设置 . 例如,某些其他函数可能会像这样调用它:

    let s: &'static str = return_str();
    

    这需要 'a'static ,但它当然是不可能的 - 您的函数不会返回对静态内存的引用,它会返回一个具有严格较小生命周期的引用 . 因此,这样的函数定义是不合理的,并且被编译器禁止 .

    无论如何,在这种情况下,你需要返回一个拥有类型的值,在这种特殊情况下,它将是一个拥有的 String

    fn return_str() -> String {
        let mut string = String::new();
    
        for _ in 0..10 {
            string.push_str("ACTG");
        }
    
        string
    }
    
  • 2

    在某些情况下,您将传递一个字符串切片,并可能有条件地想要创建一个新字符串 . 在这些情况下,您可以返回Cow . 这允许在可能的情况下引用并且拥有 String 否则:

    use std::borrow::Cow;
    
    fn return_str<'a>(name: &'a str) -> Cow<'a, str> {
        if name.is_empty() {
            let name = "ACTG".repeat(10);
            name.into()
        } else {
            name.into()
        }
    }
    

相关问题