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


我在试图理解为什么我不能回来时遇到了一些麻烦 &str 从a生成的值 String (天哪,什么时候会 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
    }
}

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

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


11488
2018-04-21 19:24


起源

description 应该是对错误的描述而不是细节; fmt::Display 应该在那里根据需要用细节来增加它。 - Chris Morgan
@ChrisMorgan我来自Go作为我玩过的最新语言,我错误地认为描述方法类似于Go的Error方法。谢谢(你的)信息! - Brandon Buck


答案:


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

fn description(&self) -> &str
// Can be rewritten as
fn description<'a>(&'a self) -> &'a str

返回的指针必须至少有效 self。现在考虑 s。它将持有一个 String,一个拥有的字符串,它在函数末尾超出范围。返回将无效 &s因为 s 函数返回时消失了。 trim 返回借用的字符串切片 s,但切片只能再次有效 s 是。

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

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

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

  2. 存储一个拥有的字符串 LexicalError 本身。这可以确保您可以返回指向它的指针,该指针在整个生命周期内都有效 self。您可以添加字段 desc: String 至 LexicalError 并在构造错误时进行格式化。然后该方法将实现为

    fn description(&self) -> &str {
        &self.desc
    }
    

    如需重复使用,您可以制作 Display 写相同的字符串。

根据 的文件 ErrorDisplay 可用于提供其他细节。如果您希望在错误中包含动态数据,那么 Display 是一个很好的格式化的地方,但你可以省略它 description。这将允许使用第一种方法。


13
2018-04-21 20:04



我认为第二种选择最适合我。这导致我提出一个半相关的问题 - 是 String 和 &str 互换?或者,我想 String 和 str 在这种情况下,另一方面,你将返回借来的 &str。我对两者之间的确切差异了解不足 String 和 &str 除了它们发生时(例如,我知道字符串文字的类型以及构建字符串时比我使用的简单格式更复杂) String)以及何时(稍微)在它们之间做出选择。 - Brandon Buck
它们不可互换。一个 String 拥有UTF-8字节,而a &str 仅指向从某处借来的UTF-8字节。 String 和 &str 类似于 Vec<T> 和 &[T]。你可以借一个 String 获得一个 &str。在这种情况下,借来的切片不能比拥有更长 String。有 关于本书中字符串的章节,这可能有用。 - Ruud
我读过这本书,你所说的比我记得更有意义。也许我对语言的理解还不足以掌握这一部分。感谢您的信息,这是一个很好的帮助。 - Brandon Buck