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

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

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

1、引用與借用

在之前我們將String 類型的值返回給調用函數(shù),這樣會導致這個String會被移動到函數(shù)中,這樣在原來的作用域不可訪問了,但是我們功能一個String值得引用,這樣就不會導致這個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()
}

 運行結果所示所示:

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

以下是一張對應的示意圖:

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

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

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

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

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

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

運行一下,看下結果:

根據(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("我把你給改了..........");
}

運行代碼,再看一下結果:

 首先定義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ù)訪問的機制。

再看下以下示例:

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

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

1.2 懸垂引用

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

下面時一個懸垂應用的示例:

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

 直接運行,會報如下錯誤:

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

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

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

運行一下看看:

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

1.3 引用的規(guī)則

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

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

2、slice 類型

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

以下有個slice示例:

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

運行以下,看下結果如何: 

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

Slice 的主要結果包括2部分:

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

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

其他寫法,例如取前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 的索引必須位于有效的字符邊界內,如果嘗試從超過邊界訪問超出索引范圍將導致panic錯誤。

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

一個示例如下所示:

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

2.2 總結

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

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

相關文章

  • Rust 配置文件內容及使用全面講解

    Rust 配置文件內容及使用全面講解

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

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

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

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

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

    rust閉包的使用

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

    詳解Rust中泛型的使用

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

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

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

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

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

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

    程序在運行的過程中,總是會不可避免地產生錯誤,而如何優(yōu)雅地解決錯誤,也是語言的設計哲學之一。本文就來和大家來了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 中非常重要的復合類型,也是最強大的復合類型之一,廣泛用于屬性配置、錯誤處理、分支流程、類型聚合等場景中,本文就來介紹一下Rust 枚舉和模式匹配,感興趣的可以了解一下
    2023-12-12

最新評論