<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 引用和借用 > [references-and-borrowing.md](https://github.com/rust-lang/rust/blob/master/src/doc/book/references-and-borrowing.md) commit 6ba952020fbc91bad64be1ea0650bfba52e6aab4 這篇教程是現行 3 個 Rust 所有權系統之一。所有權系統是 Rust 最獨特且最引人入勝的特性之一,也是作為 Rust 開發者應該熟悉的。Rust 所追求最大的目標 -- 內存安全,關鍵在于所有權。所有權系統有一些不同的概念,每個概念獨自成章: - [所有權](#),關鍵章節 - 借用,你正在閱讀的這個章節 - [生命周期](#),關于借用的高級概念 這 3 章依次互相關聯,你需要完整地閱讀全部 3 章來對 Rust 的所有權系統進行全面的了解。 ### 原則(Meta) 在我們開始詳細講解之前,這有兩點關于所有權系統重要的注意事項。 Rust 注重安全和速度。它通過很多*零開銷抽象*(*zero-cost abstractions*)來實現這些目標,也就是說在 Rust 中,實現抽象的開銷盡可能的小。所有權系統是一個典型的零開銷抽象的例子。本文提到所有的分析都是**在編譯時完成的**。你不需要在運行時為這些功能付出任何開銷。 然而,這個系統確實有一個開銷:學習曲線。很多 Rust 初學者會經歷我們所謂的“與借用檢查器作斗爭”的過程,也就是指 Rust 編譯器拒絕編譯一個作者認為合理的程序。這種“斗爭”會因為程序員關于所有權系統如何工作的基本模型與 Rust 實現的實際規則不匹配而經常發生。當你剛開始嘗試 Rust 的時候,你很可能會有相似的經歷。然而有一個好消息:更有經驗的 Rust 開發者反映,一旦他們適應所有權系統一段時間之后,與借用檢查器的沖突會越來越少。 記住這些之后,讓我們來學習關于借用的內容。 ### 借用 在[所有權](#)章節的最后,我們有一個看起來像這樣的糟糕的函數: ~~~ fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) { // do stuff with v1 and v2 // hand back ownership, and the result of our function (v1, v2, 42) } let v1 = vec![1, 2, 3]; let v2 = vec![1, 2, 3]; let (v1, v2, answer) = foo(v1, v2); ~~~ 然而這并不是理想的 Rust 代碼,因為它沒有利用'借用'這個編程語言的特點。這是它的第一步: ~~~ fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 { // do stuff with v1 and v2 // return the answer 42 } let v1 = vec![1, 2, 3]; let v2 = vec![1, 2, 3]; let answer = foo(&v1, &v2); // we can use v1 and v2 here! ~~~ 與其獲取`Vec<i32>`作為我們的參數,我們獲取一個引用:`&Vec<i32>`。并與其直接傳遞`v1`和`v2`,我們傳遞`&v1`和`&v2`。我們稱`&T`類型為一個”引用“,而與其擁有這個資源,它借用了所有權。一個借用變量的綁定在它離開作用域時并不釋放資源。這意味著`foo()`調用之后,我們可以再次使用原始的綁定。 引用是不可變的,就像綁定一樣。這意味著在`foo()`中,向量完全不能被改變: ~~~ fn foo(v: &Vec<i32>) { v.push(5); } let v = vec![]; foo(&v); ~~~ 有如下錯誤: ~~~ error: cannot borrow immutable borrowed content `*v` as mutable v.push(5); ^ ~~~ 放入一個值改變了向量,所以我們不允許這樣做 ### `&mut`引用 這有第二種類型的引用:`&mut T`。一個“可變引用”允許你改變你借用的資源。例如: ~~~ let mut x = 5; { let y = &mut x; *y += 1; } println!("{}", x); ~~~ 這會打印`6`。我們讓`y`是一個`x`的可變引用,接著把`y`指向的值加一。你會注意到`x`也必須被標記為`mut`,如果它不是,我們不能獲取一個不可變值的可變引用。 你也會發現我們在`y`前面加了一個星號(`*`),成了`*y`,這是因為`y`是一個`&mut`引用。你也需要使用他們(星號)來訪問引用的內容。 否則,`&mut`引用就像一個普通引用。這兩者之間,以及它們是如何交互的*有*巨大的區別。你會發現在上面的例子有些不太靠譜,因為我們需要額外的作用域,包圍在`{`和`}`之間。如果我們移除它們,我們得到一個錯誤: ~~~ error: cannot borrow `x` as immutable because it is also borrowed as mutable println!("{}", x); ^ note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends let y = &mut x; ^ note: previous borrow ends here fn main() { } ^ ~~~ 正如這個例子表現的那樣,有一些規則是你必須要掌握的。 ### 規則 Rust 中的借用有一些規則: 第一,任何借用必須位于比擁有者更小的作用域。第二,同一個作用域下,不能同時存在可變和不可變的引用: - 0 個或 N 個資源的引用(&T) - 只有 1 個可變引用(&mut T) 你可能注意到這些看起來很眼熟,雖然并不完全一樣,它類似于數據競爭的定義: > 當 2 個或更多個指針同時訪問同一內存位置,當它們中至少有 1 個在寫,同時操作并不是同步的時候存在一個“數據競爭” 通過引用,你可以擁有你想擁有的任意多的引用,因為它們沒有一個在寫。如果你在寫,并且你需要2個或更多相同內存的指針,則你只能一次擁有一個`&mut`。這就是Rust如何在編譯時避免數據競爭:如果打破規則的話,我們會得到錯誤。 在記住這些之后,讓我們再次考慮我們的例子。 ### 理解作用域(Thinking in scopes) 這是代碼: ~~~ let mut x = 5; let y = &mut x; *y += 1; println!("{}", x); ~~~ 這些代碼給我們如下錯誤: ~~~ error: cannot borrow `x` as immutable because it is also borrowed as mutable println!("{}", x); ^ ~~~ 這是因為我們違反了規則:我們有一個指向`x`的`&mut T`,所以我們不允許創建任何`&T`。一個或另一個。錯誤記錄提示了我們應該如何理解這個錯誤: ~~~ note: previous borrow ends here fn main() { } ^ ~~~ 換句話說,可變借用在剩下的例子中一直存在。我們需要的是可變借用在我們嘗試調用`println!`*之前*結束并生成一個不可變借用。在 Rust 中,借用綁定在借用有效的作用域上。而我們的作用域看起來像這樣: ~~~ let mut x = 5; let y = &mut x; // -+ &mut borrow of x starts here // | *y += 1; // | // | println!("{}", x); // -+ - try to borrow x here // -+ &mut borrow of x ends here ~~~ 這些作用域沖突了:我們不能在`y`在作用域中時生成一個`&x`。 所以我們增加了一個大括號: ~~~ let mut x = 5; { let y = &mut x; // -+ &mut borrow starts here *y += 1; // | } // -+ ... and ends here println!("{}", x); // <- try to borrow x here ~~~ 這就沒有問題了。我們的可變借用在我們創建一個不可變引用之前離開了作用域。不過作用域是看清一個借用持續多久的關鍵。 ### 借用避免的問題(Issues borrowing prevents) 為什么要有這些限制性規則?好吧,正如我們記錄的,這些規則避免了數據競爭。數據競爭能造成何種問題呢?這里有一些。 ### 迭代器失效(Iterator invalidation) 一個例子是“迭代器失效”,它在當你嘗試改變你正在迭代的集合時發生。Rust 的借用檢查器阻止了這些發生: ~~~ let mut v = vec![1, 2, 3]; for i in &v { println!("{}", i); } ~~~ 這會打印出 1 到 3.因為我們在向量上迭代,我們只得到了元素的引用。同時`v`本身作為不可變借用,它意味著我們在迭代時不能改變它: ~~~ let mut v = vec![1, 2, 3]; for i in &v { println!("{}", i); v.push(34); } ~~~ 這里是錯誤: ~~~ error: cannot borrow `v` as mutable because it is also borrowed as immutable v.push(34); ^ note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends for i in &v { ^ note: previous borrow ends here for i in &v { println!(“{}”, i); v.push(34); } ^ ~~~ 我們不能修改`v`因為它被循環借用。 ### 釋放后使用 引用必須與它引用的值存活得一樣長。Rust 會檢查你的引用的作用域來保證這是正確的。 如果 Rust 并沒有檢查這個屬性,我們可能意外的使用了一個無效的引用。例如: ~~~ let y: &i32; { let x = 5; y = &x; } println!("{}", y); ~~~ 我們得到這個錯誤: ~~~ error: `x` does not live long enough y = &x; ^ note: reference must be valid for the block suffix following statement 0 at 2:16... let y: &i32; { let x = 5; y = &x; } note: ...but borrowed value is only valid for the block suffix following statement 0 at 4:18 let x = 5; y = &x; } ~~~ 換句話說,`y`只在`x`存在的作用域中有效。一旦`x`消失,它變成無效的引用。為此,這個錯誤說借用“并沒有存活得足夠久”因為它在應該有效的時候是無效的。 當引用在它引用的變量*之前*聲明會導致類似的問題: ~~~ let y: &i32; let x = 5; y = &x; println!("{}", y); ~~~ 我們得到這個錯誤: ~~~ error: `x` does not live long enough y = &x; ^ note: reference must be valid for the block suffix following statement 0 at 2:16... let y: &i32; let x = 5; y = &x; println!("{}", y); } note: ...but borrowed value is only valid for the block suffix following statement 1 at 3:14 let x = 5; y = &x; println!("{}", y); } ~~~ 在上面的例子中,`y`在`x`之前被聲明,意味著`y`比`x`生命周期更長,這是不允許的。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看