我在尝试理解为什么我无法返回&str
生成的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
}
}
(对于完整代码段,此处为playpen)
我无法弄清楚如何从description
返回&amp; str,我想重复使用Display
逻辑,除非我完全不知道误解description
应该返回的内容(也许是问题的简短描述)。要么,format!(...)
返回{{1}}也会遇到同样的问题。这是一个变量,我似乎无法活到足够长的时间对我有用。
答案 0 :(得分:13)
首先,让我们来看看实际预期的寿命。 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
。不幸的是,您无法在此处自由选择返回类型。
要返回一个比方法调用更长的字符串切片,我会看到两个选项:
使用&'static
字符串切片。这肯定比调用更长,但它要求在编译时知道字符串。字符串文字的类型为&'static str
。如果描述不包含任何动态数据,则这是一个合适的选项。
将拥有的字符串存储在LexicalError
本身。这可以确保您可以返回指向它的指针,该指针对self
的整个生命周期有效。您可以向desc: String
添加字段LexicalError
,并在构造错误时执行格式设置。然后该方法将实现为
fn description(&self) -> &str {
&self.desc
}
为了重复使用,您可以使Display
写相同的字符串。
根据documentation of Error
,Display
可用于提供其他详细信息。如果您希望在错误中包含动态数据,那么Display
是格式化它的好地方,但您可以省略它description
。这将允许使用第一种方法。