最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文掌握Rust編程中的生命周期

 更新時間:2023年11月28日 15:41:05   作者:二進制空間安全  
在Rust語言中, 每一個引用都有其生命周期, 通俗講就是每個引用在程序執(zhí)行的過程中都有其自身的作用域, 一旦離開其作用域, 其生命周期也宣告結(jié)束, 值不再有效,這篇文章主要介紹了Rust編程中的生命周期,需要的朋友可以參考下

1.摘要

生命周期在Rust編程中是一個重要概念, 它能確保引用像預(yù)期的那樣一直有效。在Rust語言中, 每一個引用都有其生命周期, 通俗講就是每個引用在程序執(zhí)行的過程中都有其自身的作用域, 一旦離開其作用域, 其生命周期也宣告結(jié)束, 值不再有效。幸運的是, 在絕大多數(shù)時間里, 生命周期是隱含且可以進行推斷的, 類似于當有多種可能的類型時必須注明類型, 正因為如此, 所以Rust需要使用者使用泛型生命周期參數(shù)來注明它們的關(guān)系, 從而確保程序運行時實際使用的引用絕對有效。

2.懸垂引用問題

懸垂引用會導(dǎo)致Rust編程中出現(xiàn)一些潛在的安全問題, 例如: 程序在無意之中引用了非預(yù)期引用的數(shù)據(jù), 而這種現(xiàn)象在沒有任何約束的情況下很容易出現(xiàn)。Rust編程中引入生命周期的主要原因就是避免編程過程中出現(xiàn)的懸垂引用問題。

下面看一個代碼示例:

fn main() {
   let num;
   {
      let count = 5;
      num = &count;
   }
   println!("num: {}", num);
}

首先定義了一個變量num, 下面的花括號表示進入到一個作用域, 在該作用域中, 定義了一個變量count,并賦值為5, 在這個內(nèi)部作用域中,&count表示一個對變量count的引用, 然后將其賦給變量num, 在作用域的外部, 調(diào)用println打印出num的值。

先嘗試編譯一下這段代碼試試:

Rust編譯器報錯的地方指向代碼: num = &count, 并報了一個錯誤:"borrowed value does not live long enough", 意思是&count的值并沒有存在足夠久, 并很貼心的用藍色字告訴我們作用域的范圍界定。那么有一個問題, Rust編譯器是以什么機制來判定作用域使用的合法性呢?

3.Rust檢查機制

在Rust編譯器中, 有一個被稱為借用檢查器的機制, 它的主要工作原理是通過比較作用域來確保代碼中所有的借用都是有效的, 看一下下面的代碼標識:

fn main() {
   let num;    ------------------------- num_s
   {                                   |
      let count = 5; ------ count_s    |
      num = &count;  ---------         |
   }                                   |
   println!("num: {}", num);------------
}

這里將上面代碼中的兩個關(guān)鍵變量num和count分別引入一個各自代表其生命周期的標識:num_s和count_s。很明顯可以看到, num變量的起點在作用域上面, 終點在作用域下面,。而count_s的生命周期起點在進入第一個花括號后面, 終點在第二個花括號前面, 也就是說, num變量的生命周期num_s包含了count_s的生命周期, 所以Rust編譯器利用借用檢查器比較兩個變量的生命周期大小, 很容易推斷出num的生命周期明顯要長。

上面的代碼被Rust編譯器拒絕編譯, 正是因為借用檢查器首先發(fā)現(xiàn) num_s的生命周期比count_s要長, 而num = &count這句代碼, 被引用的對象&count比引用者num存在的時間更短, 因此產(chǎn)生了懸垂引用。

那么解決該問題的方式也比較簡單, 只要被引用對象和引用者處于同一作用域即可解決, 如下代碼:

方式一:

fn main() {
   let count = 5;
   let num = &count;
   println!("num: {}", num);
}

方式二:

fn main() {
    let num;
    {
        let count = 5;
        num = &count;
        println!("num: {}", num);
    }
}

4.泛型生命周期

下面有一段代碼, 主要完成了兩個字符串的長度比較功能, 其中compare函數(shù)負責完成兩個字符串的長度比較并返回長度最長的字符串的

切片。代碼如下:

fn compare(a: &str, b: &str) -> &str {
    if a.len() > b.len() {
       a
    } else {
       b
    }
}
?
fn main() {
   let sample1 = String::from("sample for suntiger");
   let sample2 = "suntiger";
   let c_result = compare(sample1.as_str(), sample2);
   println!("最長的字符串是 {}", c_result);
}

這段代碼編譯時,Rust編譯器的返回如下:

上面的錯誤提示分為三個部分: compare函數(shù)的兩個參數(shù)以及返回值存在生命周期問題。首先, Rust編譯器并不清楚將要返回的引用&str到底是指向參數(shù)a還是參數(shù)b, 其實作為程序員自己也是不知道的, 因為只有在運行時通過比較兩個參數(shù)的長度大小后才知道哪個參數(shù)切片的字符串內(nèi)容更長。

因此, 根據(jù)Rust編譯器的綠色標記提示, 在編寫compare函數(shù)時, 必須增加泛型生命周期參數(shù)來定義引用間的關(guān)系以便Rust的檢查機制能夠正確分析。

5.生命周期注解

在上面的編譯器返回提示中, 綠色的部分: <'a>、&'a被稱為生命周期注解, 這個也是Rust語言獨特的語法, 看起來比較奇葩和抽象, 那么Rust如何去定義這個注解呢, 以下是簡單的語法:

&str        // 稱為引用
&'a str     // 稱為帶有顯式生命周期的引用
&'a mut str // 稱為帶有顯式生命周期的可變引用

生命周期注解的一個重要作用就是告訴Rust編譯器在多個引用的泛型生命周期參數(shù)存在期間它們?nèi)绾蜗嗷ヂ?lián)系。

嘗試將compare函數(shù)代碼修改如下:

fn compare<'a>(a: &'a str, b: &'a str) -> &'a str {
    if a.len() > b.len() {
       a
    } else {
       b
    }
}

再次嘗試編譯, Rust編譯器返回如下:

這次返回了正確的結(jié)果, 當在函數(shù)中使用生命周期注解時, 這些注解只存在于函數(shù)簽名中, 而不存在于函數(shù)體的任何代碼中, 當在實際應(yīng)用過程中, 參數(shù)的引用傳給compare函數(shù)時, 被'a取代的具體生命周期是參數(shù)a的作用域與參數(shù)b的作用域重疊的那一部分, 換句話說就是兩個參數(shù)中生命周期較小的那一個。

6.結(jié)構(gòu)體生命周期注解

在定義結(jié)構(gòu)體時, 也要在相應(yīng)的地方加上生命周期注解, 結(jié)構(gòu)體定義如下:

struct PersonInfo<'a> {
    name: &'a str,
}

在該結(jié)構(gòu)體中定義了一個name的字段, 其中存放了一個字符串切片, 為了能夠在結(jié)構(gòu)體定義中使用生命周期參數(shù), 必須在結(jié)構(gòu)體名稱后面的括號中聲明泛型生命周期參數(shù)。

接下來需要在main函數(shù)中創(chuàng)建一個結(jié)構(gòu)體實例, 將一個字符串切片內(nèi)容傳給結(jié)構(gòu)體參數(shù), 代碼如下:

fn main() {
    let sayinfo = String::from("今天天氣不錯#挺風和日麗的...");
    let headerinfo = sayinfo.split('#').next().expect("找不到分隔符'#'");
    let pi = PersonInfo {
        name: headerinfo,
    };
    println!("分割name內(nèi)容為: {}", pi.name);
}

在上面的代碼中, 對變量sayinfo中的內(nèi)容作了字符串分割, 如果找到符號#,則取前面的內(nèi)容,然后將該部分內(nèi)容存到結(jié)構(gòu)體字段中。

編譯結(jié)果如下:

因為變量sayinfo在結(jié)構(gòu)體PersonInfo之前創(chuàng)建, 且結(jié)構(gòu)體離開作用域之后,變量sayinfo仍然不會離開作用域, 因此PersonInfo實例中的引用一直都是有效的, 并不會出問題。

7.靜態(tài)生命周期

靜態(tài)生命周期和靜態(tài)變量一樣, 都有一個關(guān)鍵字: static, 例子代碼如下:

let sample: &'static str = "我是一個靜態(tài)周期的例子.";

現(xiàn)在變量sample的生命周期會一直持續(xù), 在整個程序中都是有效的, 盡管靜態(tài)生命周期會避免編碼過程中的很多編譯器檢查錯誤, 但是一旦在編碼過程中出現(xiàn)懸垂引用的錯誤編碼時, 更正確的做法應(yīng)該是想辦法解決懸垂引用的問題,而不是靠靜態(tài)生命周期避開錯誤。

8.總結(jié)

在本篇文章中我們探索了生命周期在Rust常見場景中的各種應(yīng)用, 但在復(fù)雜的業(yè)務(wù)場景中, 可能還會遇到其它錯誤, 這時候依靠Rust編譯器強大的提示功能應(yīng)該能夠準確找到出現(xiàn)問題的地方, 在這個過程中解決問題, 除了加深印象, 還能起到舉一反三的作用。

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

相關(guān)文章

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

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

    隨著項目的進展,關(guān)于Rust的故事又翻開了新的一頁,今天來到了服務(wù)器端的開發(fā)場景,發(fā)現(xiàn)錯誤處理中的錯誤類型轉(zhuǎn)換有必要分享一下,對Rust錯誤處理相關(guān)知識感興趣的朋友一起看看吧
    2023-09-09
  • Windows下Rust自定義路徑安裝全攻略【保姆級教程】

    Windows下Rust自定義路徑安裝全攻略【保姆級教程】

    Rust被設(shè)計為能夠處理大量的并發(fā)和高性能的軟件,這使得它適合在游戲開發(fā)、操作系統(tǒng)開發(fā)、瀏覽器引擎開發(fā)以及嵌入式系統(tǒng)等領(lǐng)域發(fā)揮巨大的作用,這篇文章主要介紹了Windows下Rust自定義路徑安裝的相關(guān)資料,需要的朋友可以參考下
    2026-02-02
  • Rust中箱、包和模塊的學(xué)習(xí)筆記

    Rust中箱、包和模塊的學(xué)習(xí)筆記

    Rust中有三個重要的組織概念:箱、包、模塊,本文主要介紹了Rust中箱、包和模塊的學(xué)習(xí)筆記,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-03-03
  • 一文帶你了解Rust是如何處理錯誤的

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

    程序在運行的過程中,總是會不可避免地產(chǎn)生錯誤,而如何優(yōu)雅地解決錯誤,也是語言的設(shè)計哲學(xué)之一。本文就來和大家來了Rust是如何處理錯誤的,感興趣的可以了解一下
    2022-11-11
  • libbpf和Rust開發(fā)ebpf程序?qū)崙?zhàn)示例

    libbpf和Rust開發(fā)ebpf程序?qū)崙?zhàn)示例

    這篇文章主要為大家介紹了libbpf和Rust開發(fā)ebpf程序?qū)崙?zhàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • Rust中::和.的區(qū)別解析

    Rust中::和.的區(qū)別解析

    Rust中的::和.是兩種常用的操作符,分別用于訪問命名空間中的成員和實例的字段或方法,感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • 90%的Rust新手都不知道的3個實用開發(fā)技巧小結(jié)

    90%的Rust新手都不知道的3個實用開發(fā)技巧小結(jié)

    Rust是一個新興的系統(tǒng)級編程語言,以其獨特的所有權(quán)系統(tǒng)和借用檢查器而聞名,盡管它被認為是一門相對較難的語言,但只要掌握了正確的學(xué)習(xí)方法,你會發(fā)現(xiàn)Rust其實并不復(fù)雜,這篇文章主要介紹了90%的Rust新手都不知道的3個實用開發(fā)技巧,需要的朋友可以參考下
    2026-06-06
  • 深入了解Rust中trait的使用

    深入了解Rust中trait的使用

    先前我們提到過?trait,那么Rust中的trait?是啥呢?本文將通過一些示例為大家詳細講講Rust中trait的使用,感興趣的小伙伴可以了解一下
    2022-11-11
  • Rust路由匹配與參數(shù)提取從 match 語句到 axum 的類型魔法

    Rust路由匹配與參數(shù)提取從 match 語句到 axum 的類型魔法

    本文將深入探討 Rust生態(tài)中路由匹配與參數(shù)提取的實現(xiàn)機制,我們將從路由的基本概念出發(fā),逐步過渡到現(xiàn)代Rust Web 框架 axum 的實戰(zhàn),感興趣的朋友跟隨小編一起看看吧
    2026-03-03
  • Rust如何使用Sauron實現(xiàn)Web界面交互

    Rust如何使用Sauron實現(xiàn)Web界面交互

    Sauron?是一個多功能的?Web?框架和庫,用于構(gòu)建客戶端和/或服務(wù)器端?Web?應(yīng)用程序,重點關(guān)注人體工程學(xué)、簡單性和優(yōu)雅性,這篇文章主要介紹了Rust使用Sauron實現(xiàn)Web界面交互,需要的朋友可以參考下
    2024-03-03

最新評論

六盘水市| 阜城县| 五河县| 满洲里市| 克什克腾旗| 息烽县| 封丘县| 西贡区| 垫江县| 梁平县| 恭城| 岳普湖县| 钦州市| 叙永县| 天全县| 若羌县| 乌兰察布市| 黄陵县| 肃北| 华容县| 顺昌县| 高邑县| 河北区| 拉孜县| 金坛市| 新干县| 大姚县| 新竹县| 虞城县| 武功县| 隆子县| 青河县| 句容市| 南平市| 色达县| 雷波县| 扎囊县| 南川市| 兴仁县| 垦利县| 华安县|