日韩性视频-久久久蜜桃-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 引用和借阅的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 色人人| 中文字字幕在线 | 日韩欧美成人精品 | 69精品久久久久久久 | 国产精品99无码一区二区视频 | 激情内射亚洲一区二区三区爱妻 | 18xxxx日本| 日韩毛片免费观看 | 337p色噜噜| 日本福利小视频 | 99re这里只有精品在线 | 精品综合久久久 | 亚洲爽片 | 午夜激情一区二区 | 国产在线久 | 骚色综合 | 国语对白av | 中文字幕av久久爽 | 亚洲区免费 | 人妻久久一区二区 | 欧洲女性下面有没有毛发 | 狠狠操网址| 性欧美大战久久久久久久免费观看 | √资源天堂中文在线 | 国产视频一区二区在线播放 | 黑人操白妞 | 青草青青视频 | 天天5g天天爽免费观看 | 久久免费视频6 | 手机在线小视频 | 久久精品蜜桃 | 中文字幕人妻一区 | 亚洲精品少妇 | 日韩综合区 | 黄色动漫免费在线观看 | 欧美成人h| 超碰2021| 免费国产a级片 | 视频在线免费观看 | 国产一区日本 | 日韩高清影视在线观看 | 久久中文字幕无码 | 99国产精品99| 日韩精品视频在线观看免费 | 成人小视频免费看 | 久久久久久久一区二区 | 九九视频在线 | 亚洲成人精品久久 | 一级片在线观看免费 | 国产又大又粗又硬 | 国产在线一二 | 夜夜高潮夜夜爽 | 又黄又高潮的视频 | 五月激情视频 | 丁香免费视频 | 亚洲av永久无码精品一百度影院 | 欧美日韩a | 日韩a√ | 国产破处av | 国产一级在线免费观看 | avt天堂网| 91草视频 | 一区二区三区福利视频 | 国模无码一区二区三区 | 操穴影院| 日本在线视频二区 | 亚洲精品国产99 | 50度灰在线 | 亚洲精品国产精品国自产网站按摩 | 中文字幕第100页 | 欧美一级淫片bbb一84 | 日本美女久久 | 99久久婷婷| 精品一区久久久 | 国产精品亚洲αv天堂无码 伊人性视频 | 一区二区三区免费高清视频 | 久久久久久久久免费视频 | 国产精品扒开腿做爽爽 | 在线免费观看你懂的 | 婷婷视频 | 国产经典一区二区三区 | 国产精品久久久精品三级 | 澳门黄色| 短裙公车被强好爽h吃奶视频 | 日韩中文av在线 | 极品美妇后花庭翘臀娇吟小说 | 影音先锋中文字幕第一页 | 欧美777 | 四虎国产在线观看 | 不卡国产在线 | 精品成人免费视频 | 亚洲在线视频一区 | 91三级视频| 日韩成人激情 | 天天插天天摸 | 三级网站在线免费观看 | 色吟av| 三大队在线观看 | 亚洲精品色 |