struct V<'a> {
s: &'a mut String,
v: Vec<&'a String>
}
impl<'a, 'b> V<'a> {
pub fn set(&mut self, s: &'b String){
// self.s = s;
self.s.push_str(s);
self.v.push(s);
}
}
error: lifetime may not live long enough
--> src/main.rs:68:9
|
64 | impl<'a, 'b> V<'a> {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
...
68 | self.v.push(s);
| ^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`
但是
self.s.push_str(s);
还可以。它们的函数签名是相同的 (fn xxx(&mut self, &...)
)。是什么原因?我读了这篇2094-nll文章,但我仍然很困惑。
它们的函数签名是相同的( fn xxx(&mut self, &...) )。
让我们来看看这个说法。
String::push_str
pub fn push_str(&mut self, string: &str)
它需要一个
&str
,又名一片(utf-8 编码)字节,没有额外的生命周期要求。
String
具有隐式 Deref
到 &str
的转换。对于我们提供的参数 (
s: &'b String
),这会导致
&'b str
。我们可以毫无问题地调用
push_str
,因为它的参数没有生命周期要求。2.
Vec::push
pub fn push(&mut self, value: T)
当 T
绑定到
&'a String
(
Vec
的通用参数)时,变成
pub fn push(&mut self, value: &'a String)
它需要一个 &'a String
,又名对 a 的引用
String
生命周期至少与
'a
一样长的对象。我们提供的论点再次是
s: &'b String
。 生命周期
'b
没有声明它与
'a
的关系,因此编译器不能假设它更长。因此,编译器拒绝接受
s: &'b String
来代替
s: &'a String
。解决此问题的一个方法(正如编译器善意建议的那样)是要求生命周期有这样的限制
'b
:
impl<'a, 'b: 'a> V<'a> {
pub fn set(&mut self, s: &'b String){
self.s.push_str(s);
self.v.push(s);
}
}
或者,更常见的写法(因为 'b
与我们的
Vec
无关):
impl<'a> V<'a> {
pub fn set<'b: 'a>(&mut self, s: &'b String){
self.s.push_str(s);
self.v.push(s);
}
}
最后,生命周期'b
在这里实际上是完全没有必要的。 您可以在任何地方使用
'a
。 (对于函数参数,生命周期始终是最小界限)。
impl<'a> V<'a> {
pub fn set(&mut self, s: &'a String){
self.s.push_str(s);
self.v.push(s);
}
}
( 演示 )