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

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

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

1、引用與借用

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

下面是一個(gè)引用傳遞的示例:

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值的引用,用&符號(hào)代表引用

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

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

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

變量 s 有效的作用域與函數(shù)參數(shù)的作用域一樣,不過(guò)當(dāng) s 停止使用時(shí)并不丟棄引用指向的數(shù)據(jù),因?yàn)?nbsp;s 并沒(méi)有所有權(quán)。當(dāng)函數(shù)使用引用而不是實(shí)際值作為參數(shù),無(wú)需返回值來(lái)交還所有權(quán),因?yàn)榫筒辉鴵碛兴袡?quán)。

我們將創(chuàng)建一個(gè)引用的行為稱為 借用(borrowing),因?yàn)槲覀儾](méi)有擁有它的所有權(quán),只是暫時(shí)借用以下。

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

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是一個(gè)引用,因此它引用的數(shù)據(jù)不能作為可變數(shù)據(jù)借用。

1.1 可變引用

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

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í)可變的,在方法中傳遞參數(shù),也要指定引用為可變引用,因?yàn)橐弥赶虻氖潜灰玫牡刂?,所以就?huì)改變?cè)械闹怠?/p>

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

 看以下示例:

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

 根據(jù)錯(cuò)誤提示,可以知道同一時(shí)間不能多次借用str作為可變變量。Rust這樣限制是因?yàn)榭梢栽诰幾g時(shí)就避免數(shù)據(jù)競(jìng)爭(zhēng)。數(shù)據(jù)競(jìng)爭(zhēng)(data race)類似于競(jìng)態(tài)條件,它可由這三個(gè)行為造成:

  • 兩個(gè)或更多指針同時(shí)訪問(wèn)同一數(shù)據(jù)。
  • 至少有一個(gè)指針被用來(lái)寫(xiě)入數(shù)據(jù)。
  • 沒(méi)有同步數(shù)據(jù)訪問(wèn)的機(jī)制。

再看下以下示例:

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

 也會(huì)報(bào)錯(cuò),借用和可變借用不能同時(shí)被使用。

 再看下一個(gè)示例:

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

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

1.2 懸垂引用

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

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

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

 直接運(yùn)行,會(huì)報(bào)如下錯(cuò)誤:

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

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

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

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

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

1.3 引用的規(guī)則

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

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

2、slice 類型

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

以下有個(gè)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)行截取的,開(kāi)始的位置為0,長(zhǎng)度為5,所以打印的結(jié)果為hello,而world變量是從開(kāi)始索引6開(kāi)始,11結(jié)束,11-5=6,那么它的長(zhǎng)度也是5,所以打印的結(jié)果為world.

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

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

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

其他寫(xiě)法,例如取前5個(gè)字符:

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

例如取最后5個(gè)字符:

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

取整個(gè)長(zhǎng)度的切片:

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

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

 2.1 字符串字面量其實(shí)就是一個(gè)slice

一個(gè)示例如下所示:

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

2.2 總結(jié)

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

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

相關(guān)文章

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

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

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

    Rust中的Drop特性之解讀自動(dòng)化資源清理的魔法

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

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

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

    rust閉包的使用

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

    詳解Rust中泛型的使用

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

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

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

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

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

    一文帶你了解Rust是如何處理錯(cuò)誤的

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

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

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

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

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

最新評(píng)論