深入了解Rust的生命周期
Rust生命周期簡(jiǎn)介
Rust 中的每一個(gè)引用都有其 生命周期(lifetime),也就是引用保持有效的作用域。
生命周期的主要目標(biāo)是避免懸垂引用,它會(huì)導(dǎo)致程序引用了非預(yù)期引用的數(shù)據(jù)。
{
let r;
{
let x = 5;
r = &x;
}
//x出作用域后已經(jīng)被刪除,發(fā)生懸垂引用
println!("r: {}", r);
}實(shí)現(xiàn)生命周期檢查的手段:Rust 編譯器有一個(gè) 借用檢查器(borrow checker),它比較作用域來(lái)確保所有的借用都是有效的。
//函數(shù)中的泛型生命周期
fn longest(x: &str, y: &str) -> &str {
if x.len() > y.len() {
x
} else {
y
}
}
//該函數(shù)會(huì)發(fā)生編譯錯(cuò)誤,因?yàn)?Rust 并不知道將要返回的引用是指向 x 或 y
//當(dāng)我們定義這個(gè)函數(shù)的時(shí)候,并不知道傳遞給函數(shù)的具體值,所以也不知道到底是 if 還是 else 會(huì)被執(zhí)行。
//我們也不知道傳入的引用的具體生命周期,所以也就不能通過(guò)觀察作用域來(lái)確定返回的引用是否總是有效。
//借用檢查器自身同樣也無(wú)法確定,因?yàn)樗恢?x 和 y 的生命周期是如何與返回值的生命周期相關(guān)聯(lián)的。
生命周期標(biāo)注語(yǔ)法:
生命周期語(yǔ)法是用于將函數(shù)的多個(gè)參數(shù)與其返回值的生命周期進(jìn)行關(guān)聯(lián)的。一旦他們形成了某種關(guān)聯(lián),Rust 就有了足夠的信息來(lái)允許內(nèi)存安全的操作并阻止會(huì)產(chǎn)生懸垂指針亦或是違反內(nèi)存安全的行為。
Q:為什么有這個(gè)語(yǔ)法?
A:因?yàn)榫幾g器笨,借用檢查器不知道類似上述情況中的生命周期怎么比較,所以靠人手寫(xiě)給他約束。
生命周期標(biāo)注并不改變?nèi)魏我玫纳芷诘拈L(zhǎng)短。與當(dāng)函數(shù)簽名中指定了泛型類型參數(shù)后就可以接受任何類型一樣,當(dāng)指定了泛型生命周期后函數(shù)也能接受任何生命周期的引用。生命周期標(biāo)注描述了多個(gè)引用生命周期相互的關(guān)系,而不影響其生命周期。
生命周期標(biāo)注有著一個(gè)不太常見(jiàn)的語(yǔ)法:生命周期參數(shù)名稱必須以撇號(hào)(')開(kāi)頭,其名稱通常全是小寫(xiě),類似于泛型其名稱非常短。'a 是大多數(shù)人默認(rèn)使用的名稱。生命周期參數(shù)標(biāo)注位于引用的 & 之后,并有一個(gè)空格來(lái)將引用類型與生命周期標(biāo)注分隔開(kāi)。
//使用泛型生命周期標(biāo)注語(yǔ)法解決上述問(wèn)題
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
//現(xiàn)在函數(shù)簽名表明對(duì)于某些生命周期 'a,函數(shù)會(huì)獲取兩個(gè)參數(shù),他們都是與生命周期 'a 存在的一樣長(zhǎng)的字符串 slice。
//函數(shù)會(huì)返回一個(gè)同樣也與生命周期 'a 存在的一樣長(zhǎng)的字符串 slice。
//它的實(shí)際含義是 longest 函數(shù)返回的引用的生命周期與傳入該函數(shù)的引用的生命周期的較小者一致。
//這就是我們告訴 Rust 需要其保證的約束條件。
//兩個(gè)直觀的例子
//1.正確示例:返回的引用生命周期與較小的string2一致,函數(shù)調(diào)用正確
fn main() {
let string1 = String::from("long string is long");
{
let string2 = String::from("xyz");
let result = longest(string1.as_str(), string2.as_str());
println!("The longest string is {}", result);
}
}
//2.錯(cuò)誤示例:返回的引用生命周期與string2一致,但是println時(shí),result引用生命周期已經(jīng)結(jié)束,編譯失敗
fn main() {
let string1 = String::from("long string is long");
let result;
{
let string2 = String::from("xyz");
result = longest(string1.as_str(), string2.as_str());
}
println!("The longest string is {}", result);
}類似的,結(jié)構(gòu)體,方法中使用到引用時(shí)也可以使用生命周期標(biāo)注語(yǔ)法。
題外話:Rust觀法有在盡力的減輕開(kāi)發(fā)者負(fù)擔(dān),一些很常見(jiàn)的需要生命周期標(biāo)注的情況,編譯器已經(jīng)在內(nèi)部實(shí)現(xiàn)好了,未來(lái)用戶只會(huì)越來(lái)越少的使用到生命周期標(biāo)注語(yǔ)法。被Rust 官方考慮到的一些引用分析的模式被稱為 生命周期省略規(guī)則(lifetime elision rules)。
比較特殊的,'static,其生命周期能夠存活于整個(gè)程序期間。所有的字符串字面量都擁有 'static 生命周期。
//static生命周期 let s: &'static str = "I have a static lifetime.";
總結(jié):
生命周期概念和大多數(shù)語(yǔ)言一樣,但Rust對(duì)變量生命周期的檢查是很具有特色的,還有他特別的生命周期標(biāo)注語(yǔ)法是很性新穎的,能在編譯期處理的錯(cuò)誤絕不留到運(yùn)行時(shí)這是Rust很棒的設(shè)計(jì)理念.
到此這篇關(guān)于深入了解Rust的生命周期的文章就介紹到這了,更多相關(guān)Rust生命周期內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Rust制作康威生命游戲的實(shí)現(xiàn)代碼
這篇文章主要介紹了使用Rust制作康威生命游戲,初始rust項(xiàng)目,使用wasm的項(xiàng)目模板,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09
vscode搭建rust開(kāi)發(fā)環(huán)境的圖文教程
本文主要介紹了vscode搭建rust開(kāi)發(fā)環(huán)境的圖文教程,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-08-08

