Rust 生命週期 - lifetime in struct

dreamfine發表於2020-05-29

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

相關文章