我并不完全了解生命,但我认为 b
的生命将在 self
之前结束 .
那么,如何编辑这段代码呢?我在内存中复制一些东西吗?如果我创建一个新实例,这个生命周期必须遵循这种情况 .
pub struct Formater {
layout: &'static str,
}
impl Formater {
pub fn new(layout: &'static str) -> Formater {
let regex = Regex::new(r"%\{([a-z]+)(?::(.*?[^\\]))?\}").unwrap();
let b = regex.replace_all(layout, "{}");
return Formater {
layout: &b,
};
}
}
错误:
error: `b` does not live long enough
--> src/format.rs:16:22
|
16 | layout: &b,
| ^ does not live long enough
17 | };
18 | }
| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
1 回答
b
的范围是new
函数,因此在函数返回时将释放其内存 . 但是您试图从该函数返回对b
的引用 . 如果Rust允许您这样做,那么可能使用该引用的唯一代码将在值无效后使用它 . 借用检查器可以保护您免受未定义的行为 .使
layout
成为&'static str
听起来就像是让事情变得简单,但期望来自regex.replace_all
的动态分配的内存是静态的是不合理的 . 在不进入unsafe
代码的情况下,您应该将'static
生命周期中的任何内容视为编译时常量 . 例如,字符串文字 .正如其他人所说,你可能希望
layout
成为String
.String
类似于&str
,但它拥有底层str
. 这意味着当您移动String
时,基础str
随之移动 .&str
是一个参考,并且不得超过它所指向的str
的所有者 .如果你真的希望它是
&str
,另一个但不那么符合人体工程学的方法是让new()
的调用者拥有&str
,并将其作为可变引用传递给它 .这会将问题从调用堆栈向上移动一层,这意味着传递给
new
的引用将被new
突变 .现在
s
归main
所有,因此formatter
只要在比main
更小的范围内使用formatter
就有效 .但总的来说,我认为这种方法比较麻烦,除非你有充分的理由,否则你应该坚持使用
String
.