欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Rust?所有權(quán)機(jī)制原理深入剖析

 更新時(shí)間:2023年01月03日 14:01:52   作者:ooooooh灰灰  
這篇文章主要為大家介紹了Rust?所有權(quán)機(jī)制原理深入剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

what's ownership?

常見的高級(jí)語言都有自己的 Garbage Collection(GC)機(jī)制來管理程序運(yùn)行的內(nèi)存,例如 Java、Go 等。而 Rust 引入了一種全新的內(nèi)存管理機(jī)制,就是 ownership(所有權(quán))。它在編譯時(shí)就能夠保證內(nèi)存安全,而不需要 GC 來進(jìn)行運(yùn)行時(shí)的內(nèi)存回收。

在 Rust 中 ownership 有以下幾個(gè)規(guī)則:

  • 每個(gè)值都有一個(gè) woner(所有者)
  • 在同一時(shí)間,每個(gè)值只能有一個(gè) owner
  • 當(dāng) owner 離開作用域,這個(gè)值就會(huì)被丟棄

Scope (作用域)

通過作用域來劃分 owner 的生命周期,作用域是一段代碼的范圍,例如函數(shù)體、代碼塊、if 語句等。當(dāng) owner 離開作用域,這個(gè)值就會(huì)被丟棄

example:

fn main() {
    let s = String::from("hello"); // 變量 s 進(jìn)入作用域,分配內(nèi)存
    // s 在這里可用
} // 函數(shù)體結(jié)束,變量 s 離開作用域,s 被丟棄,內(nèi)存被回收

ownership transfer(所有權(quán)轉(zhuǎn)移)

和大多數(shù)語言一樣,Rust 在棧上分配基本類型的值,例如整型、浮點(diǎn)型、布爾型等。而在堆上分配復(fù)雜類型的值,例如 String、Vec 等。所以,這里就引入了兩個(gè)概念,moveclone。

move

move 操作會(huì)將變量的所有權(quán)轉(zhuǎn)移給另一個(gè)變量,這樣原來的變量就不能再使用了。這里需要注意的是,move 操作只會(huì)發(fā)生在棧上的值,因?yàn)樵诙焉系闹凳遣豢蓮?fù)制的,所以只能通過 clone 操作來復(fù)制。

example:

fn main(){
    let s1 = String::from("hello");
    let s2 = s1;
    print!("s1 = {}, s2 = {}", s1, s2);
}

在上面的代碼例子中,如果你執(zhí)行就會(huì)在編譯時(shí)報(bào)錯(cuò):

  --> src/main.rs:11:32
   |
9  |     let s1 = String::from("hello");
   |         -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait
10 |     let s2 = s1;
   |              -- value moved here
11 |     print!("s1 = {}, s2 = {}", s1, s2);
   |                                ^^ value borrowed here after move

編譯器提示我們,s1 在賦值給 s2 時(shí)發(fā)生了 move 的操作,它把字符串 hello 的所有權(quán)移交給了 s2,此時(shí) s1 的作用域到這里就結(jié)束了,所以后面再使用 s1 就會(huì)報(bào)錯(cuò)。

clone

clone 操作會(huì)將變量的值復(fù)制一份,這樣原來的變量和新的變量就都可以使用了。

這里需要注意的是,clone 操作只會(huì)發(fā)生在堆上的值,因?yàn)樵跅I系闹凳强蓮?fù)制的,所以只能通過 move 操作來轉(zhuǎn)移所有權(quán)。

example:

fn main(){
    let s1 = String::from("hello");
    let s2 = s1.clone();
    print!("s1 = {}, s2 = {}", s1, s2);
}

我們對(duì) s1 進(jìn)行 clone 操作,這樣 s1s2 都可以使用了,而且 s1 的所有權(quán)也沒有被轉(zhuǎn)移,所以后面還可以繼續(xù)使用 s1。

copy

如果一個(gè)類型實(shí)現(xiàn)了 copy 這個(gè) trait,使用它的變量不會(huì)移動(dòng),而是被簡單地復(fù)制,使它們?cè)诜峙浣o另一個(gè)變量后仍然有效。

example:

fn main() {
    let x = 5;
    let y = x;
    print!("x = {}, y = {}", x, y);
}

當(dāng) x 賦值給 y 后,xy 都可以使用,而且 x 的所有權(quán)也沒有被轉(zhuǎn)移,所以后面還可以繼續(xù)使用 x。這是因?yàn)?i32 這個(gè)類型實(shí)現(xiàn)了 copy 這個(gè) trait,所以 x 的值被復(fù)制了一份,所以 xy 都可以使用。

以下這些數(shù)據(jù)類型實(shí)現(xiàn)了 copy 這個(gè) trait:

  • 所有的整數(shù)類型,例如:u32、i32
  • 布爾類型,bool,有 truefalse 兩個(gè)值。
  • 所有的浮點(diǎn)數(shù)類型,例如:f64f32。
  • 字符類型,char。
  • 元組,當(dāng)且僅當(dāng)它們的元素類型都實(shí)現(xiàn)了 copy 這個(gè) trait。例如,(i32, i32) 實(shí)現(xiàn)了 copy,但是 (i32, String) 就沒有實(shí)現(xiàn)。

References and Borrowing(引用和借用)

我們將創(chuàng)建引用的動(dòng)作稱為借用。就像在現(xiàn)實(shí)生活中一樣,如果一個(gè)人擁有某樣?xùn)|西,你可以向他們借用。完成后,您必須將其歸還。你不擁有它。 引用有以下幾個(gè)規(guī)則:

  • 在任何給定時(shí)間,你可以擁有任意數(shù)量的引用,但是只能擁有一個(gè)可變引用。
  • 引用必須總是有效的。

example1:

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);
    println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize {
    s.len()
} // s 作用域失效,但是由于 s 是一個(gè)引用,沒有所有權(quán),所以不會(huì)發(fā)生任何事情

上面代碼中,我們使用符號(hào) & 來創(chuàng)造一個(gè)變量的引用。這里我們使用 &s1 來把這個(gè)引用指向 s1。函數(shù) calculate_length 的參數(shù) s 的類型是 &String,這意味著它是一個(gè)指向 String 類型的引用,然后在函數(shù)體內(nèi)獲取 s 的長度并返回給調(diào)用者。

example2:

fn main(){
    // 同一時(shí)間可以擁有多個(gè)不可變引用
    let s1 = String::from("hello");
    let s2 = &s1;
    let s3 = &s1;
    println!("s1 = {}, s2 = {}, s3 = {}", s1, s2, s3);
}

Mutable References(可變引用)

可變引用指的是可以改變引用值的引用。在同一作用域中,同一時(shí)間只能有一個(gè)可變引用。

example:

fn main(){
    let mut s = String::from("hello");
    change(&mut s);
    println!("{}", s);
}
fn change(some_string: &mut String) {
    some_string.push_str(", world");
}

上面代碼中,我們用 mut 先創(chuàng)建了一個(gè)可變變量 s,然后使用 &mut s 創(chuàng)建了一個(gè)指向 s 的可變引用。函數(shù) change 的入?yún)⒁彩且粋€(gè)指向 String 類型的可變引用,這樣我們就可以在函數(shù) change 中改變 s 的值了。

example2:

fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s;
    let r2 = &mut s;  // 在這里。編譯器會(huì)報(bào)錯(cuò),因?yàn)樵谕蛔饔糜蛑?,同一時(shí)間只能有一個(gè)可變引用。
    println!("{}, {}", r1, r2);
}
  --> src/main.rs:41:14
   |
40 |     let r1 = &mut s;
   |              ------ first mutable borrow occurs here
41 |     let r2 = &mut s;
   |              ^^^^^^ second mutable borrow occurs here
42 |
43 |     println!("{}, {}", r1, r2);
   |                        -- first borrow later used here

Dangling References(懸垂引用)

懸垂引用是指引用一個(gè)不存在的值。在 Rust 中,這是不可能的,因?yàn)榫幾g器會(huì)在編譯時(shí)就檢查這種情況。下面是一個(gè)例子:

fn main() {
    let reference_to_nothing = dangle(); // 獲得一個(gè)指向不存在值的引用
}
fn dangle() -> &String {
    let s = String::from("hello"); // s 進(jìn)入作用域
    &s // 返回 s 的引用
} // s 作用域結(jié)束,s 被丟棄,內(nèi)存被釋放
  --> src/main.rs:51:16
   |
51 | fn dangle() -> &String {
   |                ^ expected named lifetime parameter

因?yàn)樽兞?s 的作用域只在 dangle 函數(shù)內(nèi),當(dāng) dangle 函數(shù)返回 s 的引用時(shí),s 已經(jīng)被釋放了,所以這個(gè)引用就是懸垂引用了。 解決這個(gè)的方法是返回一個(gè) String 而不是一個(gè)引用,這樣 s 就不會(huì)被釋放,而是把 s 的所有權(quán)轉(zhuǎn)移給了調(diào)用者,也就不存在懸垂引用了。

fn dangle() -> String {
    let s = String::from("hello");
    s
}

以上就是Rust 所有權(quán)機(jī)制原理深入剖析的詳細(xì)內(nèi)容,更多關(guān)于Rust 所有權(quán)機(jī)制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 使用Rust實(shí)現(xiàn)日志記錄功能

    使用Rust實(shí)現(xiàn)日志記錄功能

    這篇文章主要為大家詳細(xì)介紹了使用Rust實(shí)現(xiàn)日志記錄功能的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的可以參考一下
    2024-04-04
  • Rust用宏實(shí)現(xiàn)參數(shù)可變的函數(shù)的實(shí)現(xiàn)示例

    Rust用宏實(shí)現(xiàn)參數(shù)可變的函數(shù)的實(shí)現(xiàn)示例

    本文主要介紹了Rust用宏實(shí)現(xiàn)參數(shù)可變的函數(shù)的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-03-03
  • Rust的slab庫使用場景分析

    Rust的slab庫使用場景分析

    slab 是一個(gè)輕量級(jí)、高性能的工具,非常適合管理固定大小的資源集合,尤其是在網(wǎng)絡(luò)編程和事件驅(qū)動(dòng)架構(gòu)中,這篇文章主要介紹了Rust的slab庫使用教程,需要的朋友可以參考下
    2024-12-12
  • Rust生命周期常見誤區(qū)(中英對(duì)照)全面指南

    Rust生命周期常見誤區(qū)(中英對(duì)照)全面指南

    這篇文章主要WEIDJAI?介紹了Rust生命周期常見誤區(qū)(中英對(duì)照)的全面指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • 探索Rust切片與Go有何區(qū)別

    探索Rust切片與Go有何區(qū)別

    這篇文章主要為大家介紹了Rust切片與Go的區(qū)別探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • 深入講解下Rust模塊使用方式

    深入講解下Rust模塊使用方式

    很多時(shí)候,我們寫的代碼需要按模塊組織,因?yàn)槲覀儫o法將大量的代碼都寫在一個(gè)文件上,那樣不容易維護(hù),下面這篇文章主要給大家介紹了關(guān)于Rust模塊使用方式的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • 深入了解Rust的生命周期

    深入了解Rust的生命周期

    生命周期指的是引用保持有效的作用域,Rust的每個(gè)引用都有自己的生命周期。本文將通過示例和大家詳細(xì)說說Rust的生命周期,需要的可以參考一下
    2022-12-12
  • Rust語言和C/C++區(qū)別對(duì)比,Rust和C語言哪個(gè)好

    Rust語言和C/C++區(qū)別對(duì)比,Rust和C語言哪個(gè)好

    Rust具有與C語言相當(dāng)?shù)乃俣群蛢?nèi)存效率,但無需手動(dòng)內(nèi)存管理或垃圾回收,它擁有出色的工具支持、友好的編譯器和不斷發(fā)展的開發(fā)者社區(qū),使用Rust能提升程序性能,最重要的是,對(duì)Python開發(fā)者而言,Rust比C語言更容易學(xué)習(xí)
    2025-02-02
  • 使用Cargo工具高效創(chuàng)建Rust項(xiàng)目

    使用Cargo工具高效創(chuàng)建Rust項(xiàng)目

    這篇文章主要介紹了使用Cargo工具高效創(chuàng)建Rust項(xiàng)目,本文有關(guān)Cargo工具的使用和Rust輸入輸出知識(shí)感興趣的朋友一起看看吧
    2022-08-08
  • Rust語言實(shí)現(xiàn)圖像編碼轉(zhuǎn)換

    Rust語言實(shí)現(xiàn)圖像編碼轉(zhuǎn)換

    image-rs庫是?Rust?社區(qū)中廣泛使用的一個(gè)開源庫,它提供了豐富的圖像編解碼功能,本文主要介紹了Rust語言實(shí)現(xiàn)圖像編碼轉(zhuǎn)換,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05

最新評(píng)論