<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                這篇教程是現行3個Rust所有權系統之一。所有權系統是Rust最獨特且最引人入勝的特性之一,也是作為Rust開發者應該熟悉的。Rust所追求最大的目標 -- 內存安全,關鍵在于所有權。所有權系統有一些不同的概念,每個概念獨自成章: * [所有權](http://kaisery.gitbooks.io/rust-book-chinese/content/content/5.8.Ownership%20%E6%89%80%E6%9C%89%E6%9D%83.md),關鍵章節 * [借用](http://kaisery.gitbooks.io/rust-book-chinese/content/content/5.9.References%20and%20Borrowing%20%E5%BC%95%E7%94%A8%E5%92%8C%E5%80%9F%E7%94%A8.md),以及它關聯的特性: "引用" (references) * 生命周期,你正在閱讀的這個章節 這3章依次互相關聯,你需要完整地閱讀全部3章來對Rust的所有權系統進行全面的了解。 ## 原則(Meta) 在我們開始詳細講解之前,這有兩點關于所有權系統重要的注意事項。 Rust注重安全和速度。它通過很多_零開銷抽象_(_zero-cost abstractions_)來實現這些目標,也就是說在Rust中,實現抽象的開銷盡可能的小。所有權系統是一個典型的零開銷抽象的例子。本文提到所有的分析都是**在編譯時完成的**。你不需要在運行時為這些功能付出任何開銷。 然而,這個系統確實有一個開銷:學習曲線。很多Rust初學者會經歷我們所謂的“與借用檢查器作斗爭”的過程,也就是指Rust編譯器拒絕編譯一個作者認為合理的程序。這種“斗爭”會因為程序員關于所有權系統如何工作的基本模型與Rust實現的實際規則不匹配而經常發生。當你剛開始嘗試Rust的時候,你很可能會有相似的經歷。然而有一個好消息:更有經驗的Rust開發者反應,一旦他們適應所有權系統一段時間之后,與借用檢查器的沖突會越來越少。 記住這些之后,讓我們來學習有關生命周期的內容。 ## 生命周期 借出一個其它人所有資源的引用可以是很復雜的。例如,想象一下下列操作: 1. 我獲取了一個某種資源的句柄 2. 我借給你了一個引用 3. 我決定不再需要這個資源了,然后釋放了它,這時你仍然持有它的引用 4. 你決定使用這個資源 噢!你的引用指向一個無效的資源。這叫做_懸垂指針_(_dangling pointer_)或者“釋放后使用”,如果這個資源是內存的話。 要修正這個問題的話,我們必須確保第四步永遠也不在第三步之后發生。Rust所有權系統通過一個叫_生命周期_(_lifetime_)的概念來做到這一點,它定義了一個引用有效的作用域。 當我們有一個獲取引用作為參數的函數,我們可以隱式或顯式涉及到引用的生命周期: ~~~ // implicit fn foo(x: &i32) { } // explicit fn bar<'a>(x: &'a i32) { } ~~~ `'a`讀作“生命周期a”。技術上講,每一個引用都有一些與之相關的生命周期,不過編譯器在通常情況讓你可以省略它們。在我們講到它之前,讓我們拆開顯式的例子看看: ~~~ fn bar<'a>(...) ~~~ 這一部分聲明了我們的生命周期。它說`bar`有一個生命周期,`'a`。如果我們有兩個生命周期,它看起來像這樣: ~~~ fn bar<'a, 'b>(...) ~~~ 接著在我們的參數列表中,我們使用了我們命名的生命周期: ~~~ ...(x: &'a i32) ~~~ 如果我們想要一個`&mut`引用,我們這么做: ~~~ ...(x: &'a mut i32) ~~~ 如果你對比一下`&mut i32`和`&'a mut i32`,他們是一樣的,只是后者在`&`和`mut i32`之間夾了一個`'a`生命周期。`&mut i32`讀作“一個`i32`的可變引用”,而`&'a mut i32`讀作“一個帶有生命周期'a的i32的可變引用”。 當你處理[結構體](http://kaisery.gitbooks.io/rust-book-chinese/content/content/5.12.Structs%20%E7%BB%93%E6%9E%84%E4%BD%93.md)時你也需要顯式的生命周期: ~~~ struct Foo<'a> { x: &'a i32, } fn main() { let y = &5; // this is the same as `let _y = 5; let y = &_y;` let f = Foo { x: y }; println!("{}", f.x); } ~~~ 如你所見,`struct`也可以有生命周期。跟函數類似的方法, ~~~ struct Foo<'a> { ~~~ 聲明一個生命周期,接著 ~~~ x: &'a i32, ~~~ 使用它。然而為什么這里我們需要一個生命周期呢?因為我們需要確保任何`Foo`的引用不能比它包含的`i32`的引用活的更久。 ## 理解作用域(Thinking in scopes) 理解生命周期的一個辦法是想象一個引用有效的作用域。例如: ~~~ fn main() { let y = &5; // -+ y goes into scope // | // stuff // | // | } // -+ y goes out of scope ~~~ 加入我們的`Foo`: ~~~ struct Foo<'a> { x: &'a i32, } fn main() { let y = &5; // -+ y goes into scope let f = Foo { x: y }; // -+ f goes into scope // stuff // | // | } // -+ f and y go out of scope ~~~ 我們的`f`生存在`y`的作用域之中,所以一切正常。那么如果不是呢?下面的代碼不能工作: ~~~ struct Foo<'a> { x: &'a i32, } fn main() { let x; // -+ x goes into scope // | { // | let y = &5; // ---+ y goes into scope let f = Foo { x: y }; // ---+ f goes into scope x = &f.x; // | | error here } // ---+ f and y go out of scope // | println!("{}", x); // | } // -+ x goes out of scope ~~~ 噢!就像你在這里看到的一樣,`f`和`y`的作用域小于`x`的作用域。不過當我們嘗試`x = &f.x`時,我們讓`x`引用一些將要離開作用域的變量。 命名作用域用來賦予作用域一個名字。有了名字是我們可以談論它的第一步。 ## 'static 叫做`static`的作用域是特殊的。它代表其具有一個整個程序的作用域。大部分Rust程序員當他們處理字符串時第一次遇到`'static`: ~~~ let x: &'static str = "Hello, world."; ~~~ 基本字符串是`&'static str`類型的因為它的引用一直有效:它們被寫入了最終庫文件的數據段。另一個例子是全局量: ~~~ static FOO: i32 = 5; let x: &'static i32 = &FOO; ~~~ 它在二進制文件的數據段中保存了一個`i32`,而`x`是它的一個引用。 ## 生命周期省略(Lifetime Elision) Rust支持強大的在函數體中的局部類型推斷,不過這在項簽名中是禁止的以便允許只通過項簽名本身推導出類型。然而,為了一些人道原因有第二個非常限制的叫做“生命周期省略”的推斷算法適用于函數簽名。它只基于簽名部分自身推斷而不涉及函數體,只推斷生命周期參數,并且只基于3個易于記憶和無歧義的規則,雖然并不隱藏它涉及到的實際類型因為局部推斷可能會適用于它。 當我們討論生命周期省略的時候,我們使用_輸入生命周期和輸出生命周期_(_input lifetime and output lifetime._)。_輸入生命周期_是關于函數參數的,而_輸出生命周期_是關于函數返回值的。例如,這個函數有一個輸入生命周期: ~~~ fn foo<'a>(bar: &'a str) ~~~ 這個有一個輸出生命周期: ~~~ fn foo<'a>() -> &'a str ~~~ 這個兩者皆有: ~~~ fn foo<'a>(bar: &'a str) -> &'a str ~~~ 這里有3條規則: * 每一個被省略的函數參數成為一個不同的生命周期參數。 * 如果確實有一個輸入生命周期,不管是否省略,這個生命周期被賦予所有函數返回值中被省略的生命周期。 * 如果這里有多個輸入生命周期,不過它們當中有一個是`&self`或者`&mut self`,`self`的生命周期被賦予所有省略的輸出生命周期。 否則,省略一個輸出生命周期將是一個錯誤。 ## 例子 這里有一些省略了生命周期的函數的例子。我們用它們的擴展形式配對了每個省略了生命周期的例子。 ~~~ fn print(s: &str); // elided fn print<'a>(s: &'a str); // expanded fn debug(lvl: u32, s: &str); // elided fn debug<'a>(lvl: u32, s: &'a str); // expanded // In the preceding example, `lvl` doesn’t need a lifetime because it’s not a // reference (`&`). Only things relating to references (such as a `struct` // which contains a reference) need lifetimes. fn substr(s: &str, until: u32) -> &str; // elided fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded fn get_str() -> &str; // ILLEGAL, no inputs fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is unclear fn get_mut(&mut self) -> &mut T; // elided fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded fn new(buf: &mut [u8]) -> BufWriter; // elided fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded ~~~
                  <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>

                              哎呀哎呀视频在线观看