008 Rust死靈書之生命週期

linghuyichong發表於2021-02-17

本系列錄製的影片主要放在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,並賦初值{123}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 協議》,轉載必須註明作者和本文連結
令狐一衝

相關文章