价值活得不够长
Value does not live long enough
我不完全理解生命周期,但我认为 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...
b
的范围是new
函数,所以它的内存会在函数returns时释放。但是您正在尝试从该函数 return 引用 b
。如果 Rust 让你这样做,唯一可能使用该引用的代码将在 值无效后使用它。借用检查器正在保护您免受 未定义行为.
将 layout
变为 &'static str
听起来像是在使事情变得简单,但是期望从 regex.replace_all
动态分配的内存是静态的是不合理的。在不进入 unsafe
代码的情况下,您应该将 'static
生命周期中的任何内容视为编译时常量。例如,字符串文字。
正如其他人所说,您可能希望 layout
成为 String
。 String
类似于 &str
,但它 拥有 基础 str
。这意味着当您移动 String
时,基础 str
也会随之移动。 &str
是一个引用,不能超过它指向的 str
的所有者。
如果您真的希望它成为 &str
,另一种不太符合人体工学的方法是让 new()
的调用者拥有 &str
,并将其作为可变参数传入参考。
pub struct Formatter<'a> {
layout: &'a str,
}
impl <'a> Formatter<'a> {
pub fn new(layout: &'a mut &str) -> Formatter<'a> {
let regex = Regex::new(r"%\{([a-z]+)(?::(.*?[^\]))?\}").unwrap();
*layout = regex.replace_all(layout, "{}");
return Formatter {
layout: layout,
};
}
}
这会将问题移到调用堆栈的上一层,这意味着您传递给 new
的引用将被 new
变异。
pub fn main() {
let mut s = "blah %{blah}";
{
let formatter = Formatter::new(&mut s);
println!("{:?}", formatter.layout); // "blah {}"
}
println!("{:?}", s); // "blah {}"
}
现在s
归main
所有,所以formatter
只要在比main
更小的范围内使用就有效。
但总的来说,我认为这种方法比较麻烦,除非你有充分的理由,否则你应该坚持使用 String
。
我不完全理解生命周期,但我认为 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...
b
的范围是new
函数,所以它的内存会在函数returns时释放。但是您正在尝试从该函数 return 引用 b
。如果 Rust 让你这样做,唯一可能使用该引用的代码将在 值无效后使用它。借用检查器正在保护您免受 未定义行为.
将 layout
变为 &'static str
听起来像是在使事情变得简单,但是期望从 regex.replace_all
动态分配的内存是静态的是不合理的。在不进入 unsafe
代码的情况下,您应该将 'static
生命周期中的任何内容视为编译时常量。例如,字符串文字。
正如其他人所说,您可能希望 layout
成为 String
。 String
类似于 &str
,但它 拥有 基础 str
。这意味着当您移动 String
时,基础 str
也会随之移动。 &str
是一个引用,不能超过它指向的 str
的所有者。
如果您真的希望它成为 &str
,另一种不太符合人体工学的方法是让 new()
的调用者拥有 &str
,并将其作为可变参数传入参考。
pub struct Formatter<'a> {
layout: &'a str,
}
impl <'a> Formatter<'a> {
pub fn new(layout: &'a mut &str) -> Formatter<'a> {
let regex = Regex::new(r"%\{([a-z]+)(?::(.*?[^\]))?\}").unwrap();
*layout = regex.replace_all(layout, "{}");
return Formatter {
layout: layout,
};
}
}
这会将问题移到调用堆栈的上一层,这意味着您传递给 new
的引用将被 new
变异。
pub fn main() {
let mut s = "blah %{blah}";
{
let formatter = Formatter::new(&mut s);
println!("{:?}", formatter.layout); // "blah {}"
}
println!("{:?}", s); // "blah {}"
}
现在s
归main
所有,所以formatter
只要在比main
更小的范围内使用就有效。
但总的来说,我认为这种方法比较麻烦,除非你有充分的理由,否则你应该坚持使用 String
。