文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
4.3 生命周期
生命周期(lifetime)是编译器比对资源所有者(owner)和借用者(borrow)存活时间的工具。根本目的,杜绝类似悬垂指针的无效引用。
多数时候,编译器能自主完成生命周期检查工作。偶尔也需手工 标记 (annotation),毕竟静态分析有许多不足和限制。当然,这只是对借用检查器(borrow checker)进行提示,并不会生成额外运行期指令,也不会对原对象有任何影响。
和 GC 运行期遍历不同,检查器要在编译期确定资源何时何处释放,就需要收集额外的信息。
&i32 // 引用。 &'a i32 // 带有生命周期标记的引用。 &'a mut i32
// implicit fn foo(x: &i32) { } // explicit fn bar<'a>(x: &'a i32) { }
下面的示例函数从逻辑上讲,没有问题。但对检查器来说却有麻烦,因为返回值生命周期和参数有关。调用时,会因参数导致安全问题。
fn longest(x: &str, y: &str) -> &str { if x.len() > y.len() { x } else { y } }
fn main() { let x = String::from("xxx"); let r: &str; { let y = String::from("yyyy"); r = longest(x.as_str(), y.as_str()); } println!("{}", r); }
如果 x.len > y.len
,逻辑正确。反过来, r
去引用生命周期更短的 y
,就有安全问题。这样就存在分歧,检查器无法作出决定。只能提示我们干预,进行标注。
error[E0106]: missing lifetime specifier | | fn longest(x: &str, y: &str) -> &str { | ---- ---- ^ expected named lifetime parameter |
标记语法和泛型类似。但要注意,生命周期标记的确切含义是:不能超出 !
- 多个相同标记的生命周期,取周期最短的作为决策依据。
- 返回值和参数用相同标记,表示不能超过参数生命周期。
标记后,检查器已经能指出具体问题所在。
// 返回值生命周期不能超过 x、y 里短的那个。 fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } } fn main() { let x = String::from("xxx"); let r: &str; { let y = String::from("yyyy"); r = longest(x.as_str(), y.as_str()); ^ borrowed value does not live long enough } - `y` dropped here while still borrowed println!("{}", r); - borrow later used here }
约束
以 'b:'a
语法声明两个生命周期长短关系: b >= a
, b
至少和 a
活得一样久。
类似的还有
T:'a
,判断类型生命周期。
依照约束,返回值生命周期不能超过参数 x
,更不能超过 y
。
fn longest<'a, 'b:'a>(x: &'a str, y: &'b str) -> &'a str { if x.len() > y.len() { x } else { y } }
调用时,编译器并不要求 实参 y
实际生命周期大过 x
。
y >= x
:符合'b:'a
约束。x >= y
:按约束要求,a
取和b
重叠部分(片段)。
fn main() { let x = String::from("xxx"); // . . . . . // . { // . let y = String::from("yyyy"); // ---+ --+ let r = longest(x.as_str(), y.as_str()); // 'b | | 'a println!("{}", r); // | | } // ---+ --+ } // . . . . .
静态
类似 C 静态局部变量,拥有进程级别的生命周期。
.data segment
fn main() { static FOO: i32 = 5; let x: &'static i32 = &FOO; }
字符串字面量也有静态生命周期。
let x: &'static str = "Hello, world.";
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论