本系列錄製的影片主要放在B站上Rust死靈書學習影片
Rust相關的原始碼資料在:github.com/anonymousGiga
今天我們跟大家聊一聊生命週期。
命週期說白了就是作用域的名字。每一個引用以及包含引用的資料結構,都要有一個生命週期來指定它保持有效的作用域。
考慮以下一段程式碼:
fn main() {
{
let mut data: Vec<i32> = vec![1, 2, 3];
{
let x: &i32 = &data[0];
{
//Vec::push(&mut data, 4);
}
println!("{}", x);
}
}
println!("Hello, world!");
}
如果去掉生命週期的語法糖,則等價於如下程式碼:
fn main() {
//等價於如下:
'a: {
let mut data: Vec<i32> = vec![1, 2, 3];
'b: {
let x: &'b i32 = Index::index::<'b>(&'b data, 0);
'c: {
//Vec::push(&'c mut data, 4);
}
println!("{}", x);
}
}
println!("Hello, world!");
}
我們先描述一下我們這段程式碼的邏輯:
1、建立一個vector data,並賦初值{1, 2, 3};
2、建立data[0]的引用x;
3、給data中新增一個元素;
4、列印整個data中的元素。
這段程式碼的邏輯是沒有問題的,但是在Rust中無法編譯透過,為什麼?
Rust可能出於如下的原因拒絕編譯這段程式碼:我們有一個有效的指向 data 的內部資料的引用 x,而同時又建立了一個 data 的可變引用用於執行push。也就是說出現了可變引用的別名,這違背了引用的第二條規則。
但是 Rust 其實並非因為這個原因判斷這段程式碼有問題。Rust 不知道 x 是 data 的子內容的引用,它其實完全不知道 Vec 的內部是什麼樣子的。它只知道 x 必須在’b 範圍內有效,這樣才能列印其中的內容。函式 Index::index 的簽名因此要求傳遞的 data 的引用也必須在’b 的範圍內有效。當我們呼叫 push 的時候,Rust 發現我們要建立一個 &’c mut data。它知道’c 是包含在’b 以內的,因為 &’b data 還存活著,所以它拒絕了這段程式。
本作品採用《CC 協議》,轉載必須註明作者和本文連結