为什么我不能返回从String生成的&str值?

Bra*_*uck 11 lifetime rust

我在试图理解为什么我不能返回一个&strString(良好,什么时候as_str准备好?)而产生的价值时遇到了一些麻烦?我做错了什么.我得到了这个想法,因为我所做的一切都没有让这个价值足够长久使用.

我正在尝试实现error::Error自定义结构:

impl error::Error for LexicalError {
    fn description(&self) -> &str {
        let s = format!("{}", self);

        // s doesn't live long enough to do this, I've tried 
        // cloning s and using that, but still the clone doesn't
        // live long enough.
        s.trim()
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}
Run Code Online (Sandbox Code Playgroud)

(对于完整的片段,这里是围栏)

我无法弄清楚如何返回&str description,我想重用Display逻辑,除非我完全误解了description应该返回的内容(也许是对问题的简短描述).要么,我得到同样的问题,返回的format!(...)是一个变量,我似乎无法活得足够长,对我有用.

Ruu*_*uud 13

首先,让我们来看看实际预期的寿命.签名中有一个隐含的生命周期description:

fn description(&self) -> &str
// Can be rewritten as
fn description<'a>(&'a self) -> &'a str
Run Code Online (Sandbox Code Playgroud)

返回的指针必须至少有效self.现在考虑s.它将保存一个String拥有的字符串,并且在函数结束时超出范围.返回它将无效&s,因为s函数返回时消失了.trim返回一个借用的字符串切片s,但切片仅在有效时才有效s.

您需要返回一个比方法调用更长的字符串切片,因此这将排除堆栈中的任何内容.如果您可以自由选择返回类型,解决方案是将字符串移出函数.为此,需要一个拥有的字符串,然后返回类型String不是&str.不幸的是,您无法在此自由选择返回类型.

要返回一个比方法调用更长的字符串切片,我看到两个选项:

  1. 使用&'static字符串切片.这肯定比调用更长,但它要求在编译时知道字符串.字符串文字有类型&'static str.如果描述不包含任何动态数据,则这是一个合适的选项.

  2. 存储LexicalError自己的字符串.这可以确保您可以返回指向它的指针,该指针在整个生命周期内都有效self.您可以添加一个字段desc: StringLexicalError和构造错误时做的格式.然后该方法将实现为

    fn description(&self) -> &str {
        &self.desc
    }
    
    Run Code Online (Sandbox Code Playgroud)

    为了重复使用,您可以使用Display相同的字符串.

根据文档Error,Display可能会用于提供额外的细节.如果您希望在错误中包含动态数据,那么它Display是格式化的好地方,但您可以省略它description.这将允许使用第一种方法.

  • `'a` 来自 `&lt;'a&gt;` 生命周期参数。除了类型参数之外,Rust 中的方法还可以具有生命周期参数。所以 `fn description&lt;'a&gt;(&amp;'a self) -&gt; &amp;'a str` 的意思是:对于每个生命周期 `'a`,如果你借出 `self` 来换取 `'a`,你会得到一个 `&amp;str` ` 这对 `'a` 有效。 (2认同)