Rust 生命周期 - lifetime in struct
出自: www.zhihu.com/column/rust-shen
上回书说到,生命周期在函数中的使用。现在我们看看结构中,为什么也要使用这玩意。
简单的说,假如我们的结构项中,需要引用某个外部的变量,我们必须保证被引用的变量生命周期要长于我们的结构。举例:
fn main() {
let opt = Option::new(1, "hello");
let svc = Service::new(&opt);
println!("Hello, {}", svc.name());
}
这段代码,看上去毫无问题,svc要引用opt, 引用前,opt就存在了。生命周期长于svc 。
因此,在设计Service这个结构和实现时,要给自己和要引用的Option,都加上时间周期,保证它们二个的生命紧密相连。于是主耶稣,就是编译器,觉得这是好的,甚是欣慰。愉快的让你通过了编译。这是完整代码:
struct Option {
pub some_int : i32,
pub some_string : String
}
impl Option {
pub fn new<T: Into<String>>(some_int : i32, some_string : T) -> Option {
Option { some_int: some_int, some_string: some_string.into() }
}
}
struct Service<'a> {
option: &'a Option
}
impl<'a> Service<'a> {
pub fn new(option: &'a Option) -> Service {
Service { option: option }
}
pub fn name(&self) -> String {
self.option.some_string.clone()
}
}
生命周期说白了就是作用域的名字。每一个引用以及包含引用的数据结构,都要有一个生命周期来指定它保持有效的作用域。
写好了这个上述代码,某天,你或者你的小傻蛋伙伴,开始使用这个”类”了, 他写下了这段代码:
fn create_service() -> Service { // compile error
let opt = Option::new(1, "hello");
Service::new(&opt);
}
编译没通过。原因是编译器发现,opt生命周期太短了,函数返回后,它就丢失了。而Service返回了一个不存在的指针。看,rust编译器这个伟大的上帝、法官。又防止了一个危险的错误。这就是Rust,把事情搞搞清楚,明确定义,以literal的形式约束。加上编译器无所不在的检查能力,就能写出让老板轻松、客户放心、程序猿操碎心的优质代码。
本作品采用《CC 协议》,转载必须注明作者和本文链接