出自: 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 協議》,轉載必須註明作者和本文連結