不知不覺也連續發文 20 天了。:.゚ヽ(*´∀`)ノ゚.:。
今天我們要來介紹其他程式語言中比較少見的機制,但是在 Rust 中是屬於和參考(reference)有關的機制,那就是生命週期(lifetime)。
生命週期是 Rust 中的一個概念,它是一個變數的有效範圍,也就是它可以被使用的範圍。生命週期的概念是為了解決 Rust 中的參考的問題,因為參考是 Rust 中的一個重要機制,它可以讓開發者在不需要複製資料的情況下,就可以使用資料。但是參考也有一個問題,就是它的生命週期,也就是它的有效範圍,如果參考的資料已經被釋放了,那麼參考就會變成一個無效的參考,這樣就會造成程式的錯誤。
這裡有一個範例:
{
let r;
{
let x = 5;
r = &x;
}
println!("r: {}", r);
}
先說結論,這個範例是沒辦法通過編譯的,也就是會報錯。
這是因為我們先宣告了一個變數 r,然後我們在一個新的區塊中宣告了一個變數 x,並且將 x 的參考賦值給 r。
這個時候,x 的生命週期就結束了,但是 r 仍然使用 x 的參考,這樣就會造成程式的錯誤。
在語法上有以下幾個重點:
生命週期參數名稱:
'
開頭'a
作為生命週期參數名稱生命週期標記的位置:
&
符號之後看一下以下的範例:
&i32 // 一個參考
&'a i32 // 一個有顯式生命週期的參考
&'a mut i32 // 一個有顯式生命週期的可變參考
單一個生命週期標記是沒有意義的,這是因為標記生命週期是為了要讓 Rust 編譯器知道多個參考的生命週期之間的關係,所以如果只有一個參考,那麼就沒有必要標記生命週期。
以下是一個範例:
fn longer<'a>(s1: &'a str, s2: &'a str) -> &'a str {
if s2.len() > s1.len() {
s2
} else {
s1
}
}
這個函式接收兩個參考,並且回傳一個參考,這個函式的生命週期參數名稱是 'a
,這個生命週期參數名稱被用在了函式的參數與回傳值上,這樣就可以讓 Rust 編譯器知道這三個參考的生命週期是相同的。
最後在執行這個函式的時候就不會問題,並且可以正常執行:
fn main() {
let r;
{
let s1 = "rust";
let s2 = "ecmascript";
r = longer(s1, s2);
println!("{} is longer", r); // ecmascript is longer
}
}
在 Rust 中,生命週期的規則有三個:
Rust 的生命週期跟所有權,兩者在其語言中的資源管理機制上都是非常重要的。由於參考是 Rust 在對於複雜類型中不可少的機制,而每個參考都有其生命週期,這是為了決定該參考是否有效的作用域。
前面有提到 Rust 的型別大多數其實都可以自動判別,而生命週期其實也一樣,都是可以自動推導出來。不過當生命週期以不同方式互相牽連的狀態下,開發者就要自行設定,這也跟型別非常複雜的狀態下,開發者就要自行設定型別一樣。
以上就是 Rust 的生命週期的基本概念,希望大家對 Rust 又更了解了一些。
本文同步發表於我的技術部落格,歡迎大家有空去參觀。