引用&借用(References&Borrowing)

如上所示,Owership讓我們改變一個變量的值變得“複雜”,那能否像其他編程語言那樣隨意改變變量的值呢?答案是有的。

所有權系統允許我們通過“Borrowing”的方式達到這個目的。這個機制非常像其他編程語言中的“讀寫鎖”,即同一時刻,只能擁有一個“寫鎖”,或只能擁有多個“讀鎖”,不允許“寫鎖”和“讀鎖”在同一時刻同時出現。當然這也是數據讀寫過程中保障一致性的典型做法。只不過Rust是在編譯中完成這個(Borrowing)檢查的,而不是在運行時,這也就是為什麼其他語言程序在運行過程中,容易出現死鎖或者野指針的問題。

通過&符號完成Borrowing:

fn main() {
    let x: Vec<i32> = vec!(1i32, 2, 3);
    let y = &x;
    println!("x={:?}, y={:?}", x, y);
}

Borrowing(&x)並不會發生所有權moved,所以println可以同時訪問x和y。 通過引用,就可以對普通類型完成修改。

fn main() {
    let mut x: i32 = 100;
    {
        let y: &mut i32 = &mut x;
        *y += 2;
    }
    println!("{}", x);
}

借用與引用的區別

借用與引用是一種相輔相成的關係,若B是對A的引用,也可稱之為B借用了A。

很相近對吧,但是借用一詞本意為要歸還。所以在Rust用引用時,一定要注意應該在何處何時正確的“歸回”借用/引用。 最後面的“高級”小節會詳細舉例。

規則

  1. 同一作用域,特定數據最多隻有一個可變借用(&mut T),或者2。
  2. 同一作用域,特定數據可有0個或多個不可變借用(&T),但不能有任何可變借用。
  3. 借用在離開作用域後釋放。
  4. 在可變借用釋放前不可訪問源變量。

可變性

Borrowing也分“不可變借用”(默認,&T)和“可變借用”(&mut T)。

顧名思義,“不可變借用”是隻讀的,不可更新被引用的內容。

fn main() {
    let x: Vec<i32> = vec!(1i32, 2, 3);

    //可同時有多個不可變借用
    let y = &x;
    let z = &x;
    let m = &x;

    //ok
    println!("{:?}, {:?}, {:?}, {:?}", x, y, z, m);
}

再次強調下,同一作用域下只能有一個可變借用(&mut T),且被借用的變量本身必須有可變性 :

fn main() {
    //源變量x可變性
    let mut x: Vec<i32> = vec!(1i32, 2, 3);

    //只能有一個可變借用
    let y = &mut x;
    // let z = &mut x; //錯誤
    y.push(100);

    //ok
    println!("{:?}", y);

    //錯誤,可變借用未釋放,源變量不可訪問
    // println!("{:?}", x);
}  //y在此處銷燬

高級例子

下面的複雜例子,進行了詳細的註釋,即使看不懂也沒關係,可以在完成Lifetimes(生命週期)的學習後再仔細思考本例子。

fn main() {
    let mut x: Vec<i32> = vec!(1i32, 2, 3);

    //更新數組
    //push中對數組進行了可變借用,並在push函數退出時銷燬這個借用
    x.push(10);

    {
        //可變借用1
        let mut y = &mut x;
        y.push(100);

        //可變借用2,注意:此處是對y的借用,不可再對x進行借用,
        //因為y在此時依然存活。
        let z = &mut y;
        z.push(1000);

        println!("{:?}", z); //打印: [1, 2, 3, 10, 100, 1000]
    } //y和z在此處被銷燬,並釋放借用。


    //訪問x正常
    println!("{:?}", x); //打印: [1, 2, 3, 10, 100, 1000]
}

總結

  1. 借用不改變內存的所有者(Owner),借用只是對源內存的臨時引用。
  2. 在借用週期內,借用方可以讀寫這塊內存,所有者被禁止讀寫內存;且所有者保證在有“借用”存在的情況下,不會釋放或轉移內存。
  3. 失去所有權的變量不可以被借用(訪問)。
  4. 在租借期內,內存所有者保證不會釋放/轉移/可變租借這塊內存,但如果是在非可變租借的情況下,所有者是允許繼續非可變租借出去的。
  5. 借用週期滿後,所有者收回讀寫權限
  6. 借用週期小於被借用者(所有者)的生命週期。

備註:   借用週期,指的是借用的有效時間段。

results matching ""

    No results matching ""