日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

未定义的引用_Rust 引用和借阅

發布時間:2025/3/13 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 未定义的引用_Rust 引用和借阅 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

清單4-5中的元組代碼的問題在于,我們必須String將調用返回 給調用函數,因此我們仍然可以String在調用to之后使用calculate_length,因為將String移到了 calculate_length。

這是定義和使用calculate_length將對象的引用作為參數的函數而不是獲取值所有權的方法:

文件名:src / main.rs

fn main() { let s1 = String::from("hello"); let len = calculate_length(&s1); println!("The length of '{}' is {}.", s1, len);}fn calculate_length(s: &String) -> usize { s.len()}

首先,請注意,變量聲明和函數返回值中的所有元組代碼都消失了。其次,請注意,我們&s1進入 calculate_length,在定義上,我們接受&String而不是 String。

這些與符號是reference,它們使您可以引用某些值而無需擁有所有權。圖4-5顯示了一個示意圖。

圖4-5:&String s指向String s1

注意:使用&進行引用的反義詞是解引用,這是通過解引用運算符來完成的*。我們將在第8章中看到解引用運算符的一些用法,并在第15章中討論解引用的細節。

讓我們在這里仔細看一下函數調用:

let s1 = String::from("hello"); let len = calculate_length(&s1);

該&s1語法讓我們創建一個基準是指它的值s1 ,但不擁有它。因為它不擁有它,所以當引用超出范圍時,它所指向的值將不會被刪除。

同樣,函數的簽名&用于指示參數的類型s是引用。讓我們添加一些解釋性注釋:

fn calculate_length(s: &String) -> usize { // s is a reference to a String s.len()} // Here, s goes out of scope. But because it does not have ownership of what // it refers to, nothing happens.

變量s有效的作用域與任何函數參數的作用域相同,但是當變量超出作用域時我們不會刪除引用指向的內容,因為我們沒有所有權。當函數將引用作為參數而不是實際值作為參數時,我們將不需要返回這些值以歸還所有權,因為我們從未擁有過所有權。

我們稱將引用作為函數參數借用。與現實生活中一樣,如果某人擁有某物,則可以向他們借用。完成后,您必須將其歸還。

那么,如果我們嘗試修改要借用的內容會怎樣?嘗試清單4-6中的代碼。劇透警報:它不起作用!

文件名:src / main.rs

fn main() { let s = String::from("hello"); change(&s);}fn change(some_string: &String) { some_string.push_str(", world");}

清單4-6:嘗試修改借入的值

這是錯誤的結果:

$ cargo run Compiling ownership v0.1.0 (file:///projects/ownership)error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` reference --> src/main.rs:8:5 |7 | fn change(some_string: &String) { | ------- help: consider changing this to be a mutable reference: `&mut std::string::String`8 | some_string.push_str(", world"); | ^^^^^^^^^^^ `some_string` is a `&` reference, so the data it refers to cannot be borrowed as mutableerror: aborting due to previous errorFor more information about this error, try `rustc --explain E0596`.error: could not compile `ownership`.To learn more, run the command again with --verbose.

正如變量在默認情況下是不可變的一樣,引用也是如此。我們不允許修改引用的內容。

可變引用

我們只需稍作調整就可以解決清單4-6中代碼中的錯誤:

文件名:src / main.rs

fn main() { let mut s = String::from("hello"); change(&mut s);}fn change(some_string: &mut String) { some_string.push_str(", world");}

首先,我們必須更改s為mut。然后,我們必須使用創建一個可變引用,&mut s并使用接受一個可變引用some_string: &mut String。

但是可變引用有一個很大的限制:您只能在一個特定范圍內對一個特定的數據進行一個可變引用。此代碼將失敗:

文件名:src / main.rs

let mut s = String::from("hello"); let r1 = &mut s; let r2 = &mut s; println!("{}, {}", r1, r2);

這是錯誤:

$ cargo run Compiling ownership v0.1.0 (file:///projects/ownership)error[E0499]: cannot borrow `s` as mutable more than once at a time --> src/main.rs:5:14 |4 | let r1 = &mut s; | ------ first mutable borrow occurs here5 | let r2 = &mut s; | ^^^^^^ second mutable borrow occurs here6 | 7 | println!("{}, {}", r1, r2); | -- first borrow later used hereerror: aborting due to previous errorFor more information about this error, try `rustc --explain E0499`.error: could not compile `ownership`.To learn more, run the command again with --verbose.

該限制允許突變,但是以非常受控的方式。這是新的Rustaceans苦苦掙扎的事情,因為大多數語言都允許您隨時更改。

具有此限制的好處是Rust可以防止在編譯時發生數據爭用。一個數據的比賽相似,競爭條件,當這三種行為的發生情況:

  • 兩個或多個指針同時訪問相同的數據。
  • 至少有一個指針用于寫入數據。
  • 沒有用于同步對數據的訪問的機制。

數據爭用會導致未定義的行為,并且在嘗試在運行時進行跟蹤時可能會難以診斷和修復。Rust阻止了此問題的發生,因為它甚至不會與數據競爭一起編譯代碼!

與往常一樣,我們可以使用大括號創建新的范圍,從而允許多個可變引用,而不能同時引用:

let mut s = String::from("hello"); { let r1 = &mut s; } // r1 goes out of scope here, so we can make a new reference with no problems. let r2 = &mut s;

對于組合可變引用和不可變引用,存在類似的規則。此代碼導致錯誤:

let mut s = String::from("hello"); let r1 = &s; // no problem let r2 = &s; // no problem let r3 = &mut s; // BIG PROBLEM println!("{}, {}, and {}", r1, r2, r3);

這是錯誤:

$ cargo run Compiling ownership v0.1.0 (file:///projects/ownership)error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable --> src/main.rs:6:14 |4 | let r1 = &s; // no problem | -- immutable borrow occurs here5 | let r2 = &s; // no problem6 | let r3 = &mut s; // BIG PROBLEM | ^^^^^^ mutable borrow occurs here7 | 8 | println!("{}, {}, and {}", r1, r2, r3); | -- immutable borrow later used hereerror: aborting due to previous errorFor more information about this error, try `rustc --explain E0502`.error: could not compile `ownership`.To learn more, run the command again with --verbose.

ew!當我們擁有不變的參考時,我們也不能擁有可變的參考。不變引用的用戶不要期望值會突然從它們下面改變!但是,可以使用多個不可變的引用,因為沒有人會影響其他任何人對數據的讀取。

請注意,引用的范圍從引入它的地方開始,一直持續到最后一次使用該引用。例如,此代碼將被編譯,因為不可變引用的最后一次使用發生在引入可變引用之前:

let mut s = String::from("hello"); let r1 = &s; // no problem let r2 = &s; // no problem println!("{} and {}", r1, r2); // r1 and r2 are no longer used after this point let r3 = &mut s; // no problem println!("{}", r3);

不可改變的引用的范圍r1和r2結束后println! ,他們最后被使用,這是可變的引用之前r3被創建。這些范圍不重疊,因此允許使用此代碼。

即使借用錯誤有時可能令人沮喪,但請記住,Rust編譯器盡早(在編譯時而不是在運行時)指出了潛在的錯誤,并確切地指出了問題出在哪里。然后,您不必追蹤為什么您的數據與您想象的不一樣。

懸掛參考

在帶有指針的語言中,很容易錯誤地創建一個懸空指針,即通過在保留指向該內存的指針的同時釋放一些內存來引用可能已分配給他人的內存中某個位置的指針。相比之下,在Rust中,編譯器保證引用永遠不會成為懸掛引用:如果您對某些數據有引用,則編譯器將確保數據不會超出對數據的引用范圍。

讓我們嘗試創建一個懸空的引用,Rust將通過編譯時錯誤防止它:

文件名:src / main.rs

fn main() { let reference_to_nothing = dangle();}fn dangle() -> &String { let s = String::from("hello"); &s}

這是錯誤:

$ cargo run Compiling ownership v0.1.0 (file:///projects/ownership)error[E0106]: missing lifetime specifier --> src/main.rs:5:16 |5 | fn dangle() -> &String { | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed fromerror: aborting due to previous errorFor more information about this error, try `rustc --explain E0106`.error: could not compile `ownership`.To learn more, run the command again with --verbose.

此錯誤消息引用的是我們尚未涵蓋的功能:生存期。我們將在第10章中詳細討論生命周期。但是,如果您忽略有關生命周期的部分,則消息的確包含了導致此代碼出現問題的關鍵:

this function's return type contains a borrowed value, but there is no valuefor it to be borrowed from.

讓我們仔細看看dangle代碼的每個階段到底發生了什么 :

文件名:src / main.rs

fn dangle() -> &String { // dangle returns a reference to a String let s = String::from("hello"); // s is a new String &s // we return a reference to the String, s} // Here, s goes out of scope, and is dropped. Its memory goes away. // Danger!

因為s是在內部創建的dangle,當代碼dangle完成時, s將被釋放。但是我們試圖返回對它的引用。這意味著此引用將指向無效String。那不好!Rust不會讓我們這樣做。

這里的解決方案是String直接返回:

fn no_dangle() -> String { let s = String::from("hello"); s}

這可以正常工作。所有權被移出,沒有任何東西被釋放。

總結

以上是生活随笔為你收集整理的未定义的引用_Rust 引用和借阅的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 97人人干| 免费无遮挡无码永久在线观看视频 | 色噜噜视频 | 久久夜精 | 女人下部全棵看视频 | 一级生活毛片 | 大肉大捧一进一出好爽mba | 菊肠扩张playh | 亚洲精品国产美女 | 亚洲一区欧洲一区 | 99精品一级欧美片免费播放 | 国产内射一区二区 | 午夜av一区 | 国产日韩视频在线观看 | 欧美在线观看一区 | 国产97视频 | 精品成人av | 国产视频高清 | aaaaaaa毛片| 色综合久久天天综合网 | 一级黄色裸体片 | 午夜视频免费在线 | 中国美女黄色 | 成人91免费视频 | a亚洲天堂| 国产成人毛毛毛片 | 午夜精品一区二区三 | 欧美日韩第一区 | 国模无码视频一区 | 九九99久久 | 亚洲v欧美v| 精品国产乱码久久久久久牛牛 | 精品xxxx| 国产精品福利片 | 日韩欧美精品在线播放 | 99久热在线精品996热是什么 | 一区二区三区视频网站 | 天堂中文在线资 | 精品成人中文无码专区 | 久久久福利 | 波多野结衣二区 | 熟女精品一区二区三区 | 日韩h在线| 无码人妻少妇伦在线电影 | 免费在线播放av | 热久久亚洲 | 少妇高潮一区二区三区99小说 | 九九免费在线视频 | 好吊色视频988gao在线观看 | 日韩中文字幕视频 | 日韩欧美中文一区 | 中日韩中文字幕一区二区 | 亚洲欧美国产高清 | 精品国产91久久久久久 | 日韩高清在线观看一区 | 国产裸体永久免费无遮挡 | 国产一级片麻豆 | 亚洲性综合网 | 国产精品成人免费一区久久羞羞 | 国产精品无码av无码 | 亚洲色图19p | 黑人激情视频 | 天天干天天操天天玩 | 久草免费在线视频 | 精品动漫一区二区三区的观看方式 | 一级丰满大乳hd高清 | 亚洲不卡视频在线 | 四虎国产成人精品免费一女五男 | 巨乳动漫美女 | 校霸被c到爽夹震蛋上课高潮 | 女同动漫免费观看高清完整版在线观看 | 久久免费视频3 | 国产一级大片在线观看 | www黄色网址 | 女人毛片视频 | 一级bbbbbbbbb毛片 | 中文字幕观看 | 亚洲成人网av | 少妇高潮21p | 久久久久欧美 | 在线天堂v | 黄色片在线免费观看 | www.久久网 | 国产在线精品视频 | 伊人青青| 亚洲男人在线天堂 | 中文字幕三级视频 | 黄色视屏在线看 | 黄色大片一级 | 伊人久久大香线蕉综合网站 | 老头老夫妇自拍性tv | 国产亚韩| 在线高清免费观看 | 一区二区乱码 | 欧洲美女与动交zozzo | 久操网站 | 国产黄片毛片 | 91中文字幕视频 | 亚洲老女人av |