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

rust引用和借用的使用小結(jié)

 更新時(shí)間:2023年01月04日 11:31:01   作者:zy010101  
在rust中,引用的語法非常簡單。通過&來取引用,通過*來解引用,這篇文章主要介紹了rust引用和借用的使用小結(jié),總的來說,借用規(guī)則,同一時(shí)刻,你只能擁有要么一個(gè)可變引用,?要么任意多個(gè)不可變引用,具體內(nèi)容詳情跟隨小編一起看看吧

引用和借用

如果每次都發(fā)生所有權(quán)的轉(zhuǎn)移,程序的編寫就會(huì)變得異常復(fù)雜。因此rust和其它編程語言類似,提供了引用的方式來操作。獲取變量的引用,稱為借用。類似于你借別人的東西來使用,但是這個(gè)東西的所有者不是你。引用不會(huì)發(fā)生所有權(quán)的轉(zhuǎn)移

引用的使用

在rust中,引用的語法非常簡單。通過&來取引用,通過*來解引用。例如:

fn main() {
    let s1: String = "Hello".to_string();
    let s2: &String = &s1;       // s2引用s1

    println!("{s1}");
    println!("{s2}");
}

這段代碼可以正常運(yùn)行,因?yàn)閟2引用的s1,不會(huì)發(fā)生所有權(quán)的轉(zhuǎn)移。再來看一個(gè)例子,通過引用來傳遞函數(shù)參數(shù)。

fn main() {
    let s = "Hello".to_string();
    let len = calculate_length(&s);     // 引用

    println!("{s}");
    println!("{len}");
}


fn calculate_length(s: &String) -> usize {
    s.len()
}   

在calculate_length中,s是一個(gè)引用,它不具備所有權(quán),因此在函數(shù)調(diào)用結(jié)束的時(shí)候,s的作用域雖然結(jié)束了,但是不會(huì)調(diào)用drop。

可變引用與不可變引用

在剛才的例子中,只是獲取了字符串的長度,相當(dāng)于我們讀取了變量。在rust中,引用默認(rèn)也是不可變的,如果需要通過引用修改變量,那么必須使用可變引用??勺円煤涂勺冏兞恳粯?,都是通過關(guān)鍵字mut來實(shí)現(xiàn)的。例如:

fn main() {
    let mut s = String::from("hello");
    change(&mut s);     // 可變引用
    println!("{s}");
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}

這段代碼輸出hello, world,可見我們通過可變引用修改了s的值,但是在這個(gè)過程中并沒有涉及所有權(quán)的轉(zhuǎn)移。

事實(shí)上,事情并沒有這么簡單??勺円貌⒉皇强梢噪S心所欲的被使用。它有一個(gè)很大的限制,“同一作用域,一個(gè)變量只能有一個(gè)可變引用”。例如:

fn main() {
    let mut s = String::from("hello");

    let r1 = &mut s;
    let r2 = &mut s;     // 同一作用域,無法創(chuàng)建兩個(gè)可變引用。

    println!("{}, {}", r1, r2);
}

兩個(gè)可變引用,可能會(huì)出現(xiàn)“同時(shí)寫入”這種情況,導(dǎo)致內(nèi)存不安全的情形發(fā)生。如果在不同的作用域,可以有多個(gè)可變引用,但是它們不能同時(shí)被擁有。例如:

fn main() {
    let mut s = String::from("hello");

    {
        let r1 = &mut s;
        println!("{r1}");
    } // r1 在這里離開了作用域,所以我們完全可以創(chuàng)建一個(gè)新的引用

    let r2 = &mut s;
    println!("{r2}");
}

同時(shí)rust也不允許同時(shí)存在可變引用和不可變引用。因?yàn)椴豢勺円每赡軙?huì)因可變引用變得失效。下面以一段C++代碼來說明這一點(diǎn)。

#include<vector>
#include<string>
#include<iostream>

using namespace std;

int main() {
    
    // 可讀引用因可變引用而變得失效
    vector<string> vs;
    vs.push_back("hello");

    auto & elem = vs[0];

    vs.push_back("world");      // push_back會(huì)導(dǎo)致vs指向的整段內(nèi)存被重新分配并移到了另一個(gè)地址,原本迭代器里面的引用就全部變成懸垂指針了。

    cout << vs[0] << endl;
    cout << elem << endl;       // 試圖使用懸垂指針
    
    return 0;
}

這段代碼執(zhí)行之后,結(jié)果如下所示:

hello
Segmentation fault (core dumped)

很明顯,這里的段錯(cuò)誤正是由于試圖使用懸垂指針引起的。而rust特殊的可變引用和不可變引用機(jī)制避免了這種錯(cuò)誤的發(fā)生。例如:

fn main() {
    let reference_to_nothing = dangle();
}

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

    &s
}   // 返回s的引用,函數(shù)結(jié)束,s移出作用域,調(diào)用drop函數(shù)清理內(nèi)存,那么返回的引用將會(huì)變成懸垂引用,從而引發(fā)錯(cuò)誤。

這段rust代碼無法編譯通過,從而避免了像上面C++代碼那樣的運(yùn)行時(shí)錯(cuò)誤。

正如Rust 程序設(shè)計(jì)語言中所言

這一限制以一種非常小心謹(jǐn)慎的方式允許可變性,防止同一時(shí)間對同一數(shù)據(jù)存在多個(gè)可變引用。新 Rustacean 們經(jīng)常難以適應(yīng)這一點(diǎn),因?yàn)榇蟛糠终Z言中變量任何時(shí)候都是可變的。這個(gè)限制的好處是 Rust 可以在編譯時(shí)就避免數(shù)據(jù)競爭。數(shù)據(jù)競爭(data race)類似于競態(tài)條件,它可由這三個(gè)行為造成:

兩個(gè)或更多指針同時(shí)訪問同一數(shù)據(jù)。
至少有一個(gè)指針被用來寫入數(shù)據(jù)。
沒有同步數(shù)據(jù)訪問的機(jī)制。

Rust 的編譯器一直在優(yōu)化,早期的時(shí)候,引用的作用域跟變量作用域是一致的,這對日常使用帶來了很大的困擾,你必須非常小心的去安排可變、不可變變量的借用,免得無法通過編譯,例如以下代碼:

fn main() {
   let mut s = String::from("hello");

    let r1 = &s;
    let r2 = &s;
    println!("{} and {}", r1, r2);
    // 新編譯器中,r1,r2作用域在這里結(jié)束

    let r3 = &mut s;
    println!("{}", r3);
} // 老編譯器中,r1、r2、r3作用域在這里結(jié)束
  // 新編譯器中,r3作用域在這里結(jié)束

在老版本的編譯器中(Rust 1.31 前),將會(huì)報(bào)錯(cuò),因?yàn)?r1 和 r2 的作用域在花括號(hào) } 處結(jié)束,那么 r3 的借用就會(huì)觸發(fā) 無法同時(shí)借用可變和不可變的規(guī)則。但是在新的編譯器中,該代碼將順利通過,因?yàn)?引用作用域的結(jié)束位置從花括號(hào)變成最后一次使用的位置,因此 r1 借用和 r2 借用在 println! 后,就結(jié)束了,此時(shí) r3 可以順利借用到可變引用。

NLL

對于這種編譯器優(yōu)化行為,Rust 專門起了一個(gè)名字 —— Non-Lexical Lifetimes(NLL),專門用于找到某個(gè)引用在作用域(})結(jié)束前就不再被使用的代碼位置。

總結(jié)

  • 總的來說,借用規(guī)則如下:
  • 同一時(shí)刻,你只能擁有要么一個(gè)可變引用, 要么任意多個(gè)不可變引用引用必須總是有效的 參考資料

Rust 程序設(shè)計(jì)語言
Rust單線程下為什么還是只能有一個(gè)可變引用呢?
Rust語言圣經(jīng)

到此這篇關(guān)于rust引用和借用的文章就介紹到這了,更多相關(guān)rust引用和借用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Rust實(shí)現(xiàn)構(gòu)建器模式和如何使用Bon庫中的構(gòu)建器

    Rust實(shí)現(xiàn)構(gòu)建器模式和如何使用Bon庫中的構(gòu)建器

    這篇文章主要介紹了Rust實(shí)現(xiàn)構(gòu)建器模式和如何使用Bon庫中的構(gòu)建器,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-08-08
  • Rust中類型轉(zhuǎn)換在錯(cuò)誤處理中的應(yīng)用小結(jié)

    Rust中類型轉(zhuǎn)換在錯(cuò)誤處理中的應(yīng)用小結(jié)

    隨著項(xiàng)目的進(jìn)展,關(guān)于Rust的故事又翻開了新的一頁,今天來到了服務(wù)器端的開發(fā)場景,發(fā)現(xiàn)錯(cuò)誤處理中的錯(cuò)誤類型轉(zhuǎn)換有必要分享一下,對Rust錯(cuò)誤處理相關(guān)知識(shí)感興趣的朋友一起看看吧
    2023-09-09
  • rust異步編程詳細(xì)講解

    rust異步編程詳細(xì)講解

    這篇文章主要介紹了rust異步編程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-12-12
  • rust 如何使用 cargo-nextest 替代 cargo test

    rust 如何使用 cargo-nextest 替代 cargo te

    cargo-nextest 是新一代的rust測試程序,能夠極大提升測試性能,可以完全替代 cargo test 命令,這篇文章主要介紹了rust 如何使用 cargo-nextest 替代 cargo test,需要的朋友可以參考下
    2024-05-05
  • 在win10上使用mingw64編譯器配置Rust開發(fā)環(huán)境和idea 配置Rust 插件

    在win10上使用mingw64編譯器配置Rust開發(fā)環(huán)境和idea 配置Rust 插件

    在win10上配置 Rust 開發(fā)環(huán)境(使用 mingw64編譯器)和 idea 配置 Rust 插件的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-03-03
  • rust的nutyp驗(yàn)證和validator驗(yàn)證數(shù)據(jù)的方法示例詳解

    rust的nutyp驗(yàn)證和validator驗(yàn)證數(shù)據(jù)的方法示例詳解

    本文介紹了在Rust語言中,如何使用nuType和validator兩種工具來對Cargo.toml和modules.rs文件進(jìn)行驗(yàn)證,通過具體的代碼示例和操作步驟,詳細(xì)解釋了驗(yàn)證過程和相關(guān)配置,幫助讀者更好地理解和掌握使用這兩種驗(yàn)證工具的方法,更多Rust相關(guān)技術(shù)資訊,可繼續(xù)關(guān)注腳本之家
    2024-09-09
  • rust文件讀寫的實(shí)現(xiàn)示例

    rust文件讀寫的實(shí)現(xiàn)示例

    Rust語言提供了強(qiáng)大的文件讀寫庫,使得開發(fā)者可以更加方便地進(jìn)行文件操作,并且其安全性可以有效避免文件操作中可能出現(xiàn)的風(fēng)險(xiǎn),本文就來詳細(xì)的介紹了rust文件讀寫的實(shí)現(xiàn)示例,感興趣的可以了解一下
    2023-12-12
  • 詳解Rust語言中anyhow的使用

    詳解Rust語言中anyhow的使用

    anyhow是一個(gè)Rust庫,用于簡化錯(cuò)誤處理和提供更好的錯(cuò)誤報(bào)告,這個(gè)庫適合用于應(yīng)用程序,而不是用于創(chuàng)建庫,因?yàn)樗峁┝艘粋€(gè)非結(jié)構(gòu)化的,方便使用的錯(cuò)誤類型,本文就給大家講講Rust語言中anyhow的使用,需要的朋友可以參考下
    2023-08-08
  • rust延遲5秒鎖屏的實(shí)現(xiàn)代碼

    rust延遲5秒鎖屏的實(shí)現(xiàn)代碼

    這篇文章主要介紹了rust延遲5秒鎖屏的實(shí)現(xiàn)代碼,文中通過實(shí)例代碼也介紹了rust計(jì)算程序運(yùn)行時(shí)間的方法,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09
  • 一文學(xué)會(huì)Rust語言如何操作JSON

    一文學(xué)會(huì)Rust語言如何操作JSON

    JSON在Web開發(fā)中被廣泛應(yīng)用于數(shù)據(jù)交換,本文主要介紹了Rust語言操作JSON,包括序列化、反序列化、JSON創(chuàng)建等多個(gè)方面,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03

最新評(píng)論