String::push_str与Vec::push的生命周期约束差异及报错原因
Rust生命周期差异问题解析
代码示例
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);可以正常编译,但self.v.push(s);触发了生命周期错误。两者调用时传入的参数形式类似(均为&mut self和一个引用参数),为何会出现这种差异?我阅读了NLL相关文档,但仍感到困惑。
核心原因:引用的使用方式差异
两者的本质区别在于是否将传入的引用长期存储到结构体中:
self.s.push_str(s)的调用逻辑push_str的方法签名是fn push_str(&mut self, string: &str),它只是临时借用s的内容来追加到self.s里,方法执行完成后就不再依赖s的引用。编译器只需要保证push_str执行期间s是有效的,不需要s的生命周期'b长于结构体的'a。self.v.push(s)的调用逻辑self.v的类型是Vec<&'a String>,这意味着它存储的所有引用必须拥有至少和结构体生命周期'a一样长的存活时间。当你把&'b String类型的s推入这个向量时,编译器必须确保'b的生命周期不短于'a——否则结构体还存在时,s引用的字符串可能已经被销毁,产生悬垂引用,这是Rust的安全规则绝对禁止的。
修复方案
给生命周期'b添加'b: 'a的约束,明确告知编译器传入的s的生命周期至少和结构体的'a一样长,代码即可正常编译:
impl<'a, 'b: 'a> V<'a> { pub fn set(&mut self, s: &'b String){ self.s.push_str(s); self.v.push(s); } }
内容的提问来源于stack exchange,提问作者杨尚山
相关产品推荐
相关产品推荐

