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

Rust中的引用與借用舉例詳解

 更新時間:2023年11月24日 11:57:49   作者:和你一起去月球  
這篇文章主要給大家介紹了關(guān)于Rust中引用與借用的相關(guān)資料,rust中借用和引用的附帶功效都一樣,就是都有生命周期,文中通過代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Rust具有一定的參考價值,需要的朋友可以參考下

1、引用與借用

在之前我們將String 類型的值返回給調(diào)用函數(shù),這樣會導(dǎo)致這個String會被移動到函數(shù)中,這樣在原來的作用域不可訪問了,但是我們功能一個String值得引用,這樣就不會導(dǎo)致這個String類型的值被移動,而傳遞的只是一個引用。引用更像一個指針,因為是一個地址,我們就可以基于這個地址找到改地址上存儲的數(shù)據(jù)。 與指針不同,引用確保指向某個特定類型的有效值。

下面是一個引用傳遞的示例:

fn main() {
    let str = String::from("hello world!");
    let len = _length(&str);
    println!("str is value: {}", str);
    println!("str length is: {}", len)
} 
fn _length(s: &String) ->usize {
    s.len()
}

 運(yùn)行結(jié)果所示所示:

根據(jù)以上代碼可以看出_length方法中傳遞的參數(shù)為&str,所以這里傳遞的是str值的引用,用&符號代表引用

以下是一張對應(yīng)的示意圖:

根據(jù)上圖也能看出s是s1的引用,引用的是s1在堆中對應(yīng)類型的值。

注意:與使用 & 引用相反的操作是 解引用(dereferencing),它使用解引用運(yùn)算符,*

變量 s 有效的作用域與函數(shù)參數(shù)的作用域一樣,不過當(dāng) s 停止使用時并不丟棄引用指向的數(shù)據(jù),因為 s 并沒有所有權(quán)。當(dāng)函數(shù)使用引用而不是實際值作為參數(shù),無需返回值來交還所有權(quán),因為就不曾擁有所有權(quán)。

我們將創(chuàng)建一個引用的行為稱為 借用(borrowing),因為我們并沒有擁有它的所有權(quán),只是暫時借用以下。

我們可以嘗試修改一下引用,把引用值改了,看下是否可以,這就類似于我借了別人的東西,然后把東西換了個樣子,看看是不是可以呢?

fn main() {
    let str = String::from("hello world!");
    let len = _length(&str);
    println!("str is value: {}", str);
} 
fn _length(s: &String) {
    s.push_str("我把你給改了..........");
}

運(yùn)行一下,看下結(jié)果:

根據(jù)提示可以s是一個引用,因此它引用的數(shù)據(jù)不能作為可變數(shù)據(jù)借用。

1.1 可變引用

允許我們修改一個借用的值,這就是 可變引用,把上面的示例改一下,如下所示:

fn main() {
    let mut str = String::from("hello world!");
    _length(&mut str);
    println!("str is value: {}", str);
} 
fn _length(s: &mut String) {
    s.push_str("我把你給改了..........");
}

運(yùn)行代碼,再看一下結(jié)果:

 首先定義str必須時可變的,在方法中傳遞參數(shù),也要指定引用為可變引用,因為引用指向的是被引用的地址,所以就會改變原有的值。

注意:可變引用有一個很大的限制:如果你有一個對該變量的可變引用,你就不能再創(chuàng)建對該變量的引用。

 看以下示例:

fn main() {
    let mut str = String::from("hello world!");
    let a = &mut str;
    let b = &mut str;
    println!("a {}, b{}", a, b)
} 

 根據(jù)錯誤提示,可以知道同一時間不能多次借用str作為可變變量。Rust這樣限制是因為可以在編譯時就避免數(shù)據(jù)競爭。數(shù)據(jù)競爭(data race)類似于競態(tài)條件,它可由這三個行為造成:

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

再看下以下示例:

fn main() {
    let mut str = String::from("hello world!");
    let c = &mut str;
    let b = &str;
    println!("b{} {}", b, c)
} 

 也會報錯,借用和可變借用不能同時被使用。

 再看下一個示例:

fn main() {
    let mut str = String::from("hello world!");
    let c = &mut str;
   
    println!("{}", c);
    let b = &str;
    println!("{}", b)
} 

 可以看到這次是可以打印處結(jié)果的,在第一次打印的時候,變量的作用域也就結(jié)束了,因而在下次進(jìn)行賦值時可以的。

1.2 懸垂引用

在具有指針的語言中,很容易通過釋放內(nèi)存時保留指向它的指針而錯誤地生成一個 懸垂指針(dangling pointer),所謂懸垂指針是其指向的內(nèi)存可能已經(jīng)被分配給其它持有者。相比之下,在 Rust 中編譯器確保引用永遠(yuǎn)也不會變成懸垂?fàn)顟B(tài):當(dāng)你擁有一些數(shù)據(jù)的引用,編譯器確保數(shù)據(jù)不會在其引用之前離開作用域。

下面時一個懸垂應(yīng)用的示例:

fn main() {
    dp();
} 
fn dp() -> &String {    // 返回字符串的引用
    let str = String::from("hello world!");   // 創(chuàng)建一個字符串
    &str      // 返回字符串的引用
}  // str 的作用域結(jié)束
// 方法返回的時字符串的引用,而字符串離開作用與,被釋放,然在此返回該字符串的引用,
// 就會導(dǎo)致返回的結(jié)果不是預(yù)期的結(jié)果,在Rust中是不讓這樣操作的。

 直接運(yùn)行,會報如下錯誤:

根據(jù)報錯可知,此函數(shù)的返回類型包含借用值,但沒有可供借用的值,在返回類型引用處,提示: 錯誤的聲明周期修飾符。

我們改以下返回字符串本身,看一下結(jié)果怎么樣?

fn main() {
    println!("value is {}", dp())
} 
fn dp() -> String {    
    let str = String::from("hello world!");   
    return str
}  

運(yùn)行一下看看:

發(fā)現(xiàn)對應(yīng)的值給打印出來,所有權(quán)交出去了,所以,可打印出對應(yīng)的值。

1.3 引用的規(guī)則

根據(jù)之前的結(jié)果,我們可以總結(jié)出以下兩點:

  • 在任意給定時間,要么 只能有一個可變引用,要么 只能有多個不可變引用。
  • 引用必須總是有效的。

2、slice 類型

 slice 允許你引用集合中一段連續(xù)的元素序列,而不用引用整個集合。slice 是一類引用,所以它沒有所有權(quán)。

以下有個slice示例:

fn main() {
        let s = String::from("hello world");
        let hello = &s[0..5];
        let world = &s[6..11];
        println!("{}---{}", hello, world)  
} 

運(yùn)行以下,看下結(jié)果如何: 

根據(jù)以上結(jié)果,可以知道hello變量從字符串(hello world)中進(jìn)行截取的,開始的位置為0,長度為5,所以打印的結(jié)果為hello,而world變量是從開始索引6開始,11結(jié)束,11-5=6,那么它的長度也是5,所以打印的結(jié)果為world.

Slice 的主要結(jié)果包括2部分:

  • 第一部分,是指針,指向數(shù)據(jù)開始的位置
  • 第二部分,是長度,就是元素結(jié)束減去開始位置的值

以下是一個示意圖,能夠更加清楚知道slice與字符串的關(guān)系:

其他寫法,例如取前5個字符:

fn main() {
        let s = String::from("hello world");
        let hello = &s[0..5];
        let hello1 = &s[..5];  // hello 和 hello1 是等價的
        println!("{}---{}", hello, hello1)  
} 

例如取最后5個字符:

fn main() {
        let s = String::from("hello world");
        let world = &s[6..];
        let world1 = &s[6..];
        println!("{}---{}", world, world1)  
} 

取整個長度的切片:

fn main() {
        let s = String::from("hello world");
        let world = &s[..];
        let world1 = &s[..];
        println!("{}---{}", world, world1)  
} 

注意:字符串 slice range 的索引必須位于有效的字符邊界內(nèi),如果嘗試從超過邊界訪問超出索引范圍將導(dǎo)致panic錯誤。

 2.1 字符串字面量其實就是一個slice

一個示例如下所示:

這里 s1 的類型是 &str:world 的類型也是&str,所以s1它是一個指向二進(jìn)制程序特定位置的 slice。這也就是為什么字符串字面值是不可變的;&str 是一個不可變引用。

2.2 總結(jié)

所有權(quán)、借用和 slice 這些概念讓 Rust 程序在編譯時確保內(nèi)存安全。Rust 語言提供了跟其他系統(tǒng)編程語言相同的方式來控制你使用的內(nèi)存,但擁有數(shù)據(jù)所有者在離開作用域后自動清除其數(shù)據(jù)的功能意味著你無須額外編寫和調(diào)試相關(guān)的控制代碼。

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

相關(guān)文章

  • Rust 配置文件內(nèi)容及使用全面講解

    Rust 配置文件內(nèi)容及使用全面講解

    這篇文章主要為大家介紹了Rust 配置文件內(nèi)容及使用全面講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • Rust中的Drop特性之解讀自動化資源清理的魔法

    Rust中的Drop特性之解讀自動化資源清理的魔法

    Rust通過Drop特性實現(xiàn)了自動清理機(jī)制,確保資源在對象超出作用域時自動釋放,避免了手動管理資源時可能出現(xiàn)的內(nèi)存泄漏或雙重釋放問題,智能指針如Box、Rc和RefCell都依賴于Drop來管理資源,提供了靈活且安全的資源管理方案
    2025-02-02
  • Rust實現(xiàn)構(gòu)建器模式和如何使用Bon庫中的構(gòu)建器

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

    這篇文章主要介紹了Rust實現(xiàn)構(gòu)建器模式和如何使用Bon庫中的構(gòu)建器,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-08-08
  • rust閉包的使用

    rust閉包的使用

    閉包在Rust中是非常強(qiáng)大的功能,允許你編寫更靈活和表達(dá)性的代碼,本文主要介紹了rust閉包的使用,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • 詳解Rust中泛型的使用

    詳解Rust中泛型的使用

    泛型是一種在編寫代碼時不指定具體類型,而在使用時再確定類型的編程技巧,本文將詳細(xì)介紹?Rust?中泛型的相關(guān)概念和用法,希望對大家有所幫助
    2023-06-06
  • 深入了解Rust中的枚舉和模式匹配

    深入了解Rust中的枚舉和模式匹配

    這篇文章主要為大家詳細(xì)介紹了Rust中的枚舉和模式匹配的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • 利用rust實現(xiàn)一個命令行工具

    利用rust實現(xiàn)一個命令行工具

    這篇文章主要為大家詳細(xì)介紹了如何使用?Rust?和?clap?4.4.0?創(chuàng)建一個命令行工具?my_dev_tool,文中的示例代碼講解詳細(xì),需要的小伙伴可以參考下
    2023-12-12
  • 一文帶你了解Rust是如何處理錯誤的

    一文帶你了解Rust是如何處理錯誤的

    程序在運(yùn)行的過程中,總是會不可避免地產(chǎn)生錯誤,而如何優(yōu)雅地解決錯誤,也是語言的設(shè)計哲學(xué)之一。本文就來和大家來了Rust是如何處理錯誤的,感興趣的可以了解一下
    2022-11-11
  • MacBook Pro安裝rust編程環(huán)境的過程

    MacBook Pro安裝rust編程環(huán)境的過程

    rustup是一個用于管理Rust版本和工具鏈的工具,這篇文章主要介紹了MacBook Pro安裝rust編程環(huán)境的過程,感興趣的朋友跟隨小編一起看看吧
    2024-02-02
  • Rust 枚舉和模式匹配的實現(xiàn)

    Rust 枚舉和模式匹配的實現(xiàn)

    枚舉是 Rust 中非常重要的復(fù)合類型,也是最強(qiáng)大的復(fù)合類型之一,廣泛用于屬性配置、錯誤處理、分支流程、類型聚合等場景中,本文就來介紹一下Rust 枚舉和模式匹配,感興趣的可以了解一下
    2023-12-12

最新評論