iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0
Rust

Rust 30 天養成計畫:從零到 CLI 專案系列 第 24

Day 24:生命週期進階與自動推導(Lifetime Elision)

  • 分享至 

  • xImage
  •  

1. 為什麼需要 Lifetime Elision
昨天學到每當函數有引用參數時,就要標註 'a 等生命週期,但如果每個地方都手動標註,程式會變得冗長。
Rust 編譯器其實能根據一些規則自動推導生命週期,這稱為 lifetime elision(生命週期省略規則)。

2. 三大自動推導規則
Rust 編譯器根據三個原則判斷要不要自動加 'a:
(1)每個參數的引用都會各自獲得一個生命週期。
(2)如果只有一個參數,那麼輸出的生命週期會與該參數相同。
(3)如果有多個參數但其中有 &self 或 &mut self,輸出生命週期與該物件一致。

3. 範例:單一參數時自動推導

fn first_word(s: &str) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..]
}

fn main() {
    let s = String::from("hello world");
    println!("{}", first_word(&s));
}

雖然這個函數的正確生命週期寫法是:

fn first_word<'a>(s: &'a str) -> &'a str

但因為它符合只有一個參數的規則,所以 'a 可以省略。
輸出:

hello

4. 多參數時的限制
當有多個引用參數時,Rust 無法自動判斷誰比較久:

fn longest(s1: &str, s2: &str) -> &str {
    if s1.len() > s2.len() {
        s1
    } else {
        s2
    }
}

這段會報錯:

error[E0106]: missing lifetime specifier

因為編譯器不知道要讓回傳值跟哪個參數綁定,必須改寫為:

fn longest<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    if s1.len() > s2.len() {
        s1
    } else {
        s2
    }
}

5. 與 struct、impl 搭配使用

struct ImportantExcerpt<'a> {
    part: &'a str,
}

impl<'a> ImportantExcerpt<'a> {
    fn announce_and_return_part(&self, announcement: &str) -> &str {
        println!("Attention: {}", announcement);
        self.part
    }
}

fn main() {
    let text = String::from("Rust makes memory safety fun!");
    let first = text.split('.').next().unwrap();
    let excerpt = ImportantExcerpt { part: first };
    println!("{}", excerpt.announce_and_return_part("Read this:"));
}

輸出:

Attention: Read this:
Rust makes memory safety fun!

這裡 &self 幫助編譯器推導出回傳值的生命週期,因此不需額外註記 'a。

6. 學習心得與補充
今天的內容讓我真正理解為什麼昨天那些 'a 有時需要、但有時可以省略。原本我以為生命週期標註只是麻煩的語法,但其實 Rust 編譯器的自動推導能力相當強大。透過三條省略規則,大部分情況下根本不需要手動標註,只有在多個參考來源或複雜邏輯中才要明確標出。我覺得這設計兼顧了安全與可讀性,需要時可以精確控制,不需要時又能保持簡潔。


上一篇
Day 23:生命週期(Lifetimes)
下一篇
Day 25:泛型、Trait Bound 與生命週期的綜合應用
系列文
Rust 30 天養成計畫:從零到 CLI 專案30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言