前言
所有權(quán)機(jī)制是Rust的核心功能之一,對(duì)于初學(xué)者算是一個(gè)重難點(diǎn),它保證了程序無(wú)需GC,即可自動(dòng)化的釋放內(nèi)存
希望這篇博客可以幫助你快速理解所有權(quán)機(jī)制
概念
Rust的值都只有一個(gè)變量是該值的所有者
所有者可以切換,但是值在任一時(shí)刻有且僅有一個(gè)所有者
當(dāng)所有者離開(kāi)作用域,該值將被丟棄
錯(cuò)誤示例
在變量的作用域之外訪問(wèn)該變量
fn main() {
{
let s = String::from("hello"); // 創(chuàng)建字符串,該字符串的所有者是變量s
} // 離開(kāi)作用域,該字符串被丟棄
println!("{}", s); // 編譯報(bào)錯(cuò),此時(shí)變量s已被釋放,無(wú)法訪問(wèn)變量s
}
訪問(wèn)一個(gè)所有權(quán)被轉(zhuǎn)移的變量
fn main() {
let s = String::from("hello"); // 創(chuàng)建字符串,該字符串的所有者是變量s
let a = s; // 字符串的所有權(quán)從變量s傳遞給變量a
println!("{}",s); // 編譯報(bào)錯(cuò),此時(shí)字符串的所有權(quán)已被轉(zhuǎn)移,無(wú)法在通過(guò)變量s訪問(wèn)字符串
}
訪問(wèn)一個(gè)所有權(quán)被轉(zhuǎn)移的變量
fn main() {
let s = String::from("hello"); // 創(chuàng)建字符串,該字符串的所有者是變量s
takes_ownership(s); // 字符串的所有權(quán)從變量s傳遞給函數(shù)takes_ownership
println!("{}",s); // 編譯報(bào)錯(cuò),此時(shí)字符串的所有權(quán)已被轉(zhuǎn)移,無(wú)法在通過(guò)變量s訪問(wèn)字符串
}
fn takes_ownership(s: String) {
println!("我拿到了字符串\"{}\"的所有權(quán)", s); // 拿到字符串的所有權(quán)
} // 離開(kāi)作用域,該字符串被丟棄
借用
在上述錯(cuò)誤示例中,我們不難發(fā)現(xiàn),如果我們把String字符串的所有權(quán)傳遞給函數(shù),那么等到函數(shù)結(jié)束,我們就無(wú)法在使用該字符串了,對(duì)于我們,這顯然是無(wú)法接受的,那么幾種解決方法解決這個(gè)問(wèn)題,例如
fn main() {
let mut s = String::from("hello");
s = takes_ownership(s);
println!("{}", s);
}
fn takes_ownership(s: String) -> String {
println!("我拿到了字符串\"{}\"的所有權(quán)", s); // 拿到字符串的所有權(quán)
s // 返回該字符串
}
fn main() {
let mut s = String::from("hello");
s = takes_ownership(s);
println!("{}", s);
}
fn takes_ownership(s: String) -> String {
println!("我拿到了字符串\"{}\"的所有權(quán)", s); // 拿到字符串的所有權(quán)
s // 返回該字符串
}
但是上述做法并不優(yōu)雅,Rust推薦的做法是我們通過(guò)借用來(lái)解決這個(gè)問(wèn)題,借用就是創(chuàng)建一個(gè)引用的行為,例如
fn main() {
let s = String::from("hello");
takes_ownership(&s); // 將字符串的引用傳遞給函數(shù)
println!("{}", s);
}
fn takes_ownership(s: &String) { // 借用到字符串的引用
println!("我借用到了字符串\"{}\"的引用", s);
} // 此時(shí)字符串的所有權(quán)并沒(méi)傳遞給函數(shù),應(yīng)此該函數(shù)沒(méi)有資格釋放該字符串
如果我們需要在函數(shù)內(nèi)部修改字符串,那么我們可以借用字符串的可變引用
fn main() {
let mut s = String::from("hello");
takes_ownership(&mut s); // 將字符串的引用傳遞給函數(shù)
println!("{}", s);
}
fn takes_ownership(s: &mut String) { // 借用到字符串的可變引用
println!("我借用到了字符串\"{}\"的可變引用", s);
s.push_str(" world"); // 修改該字符串
} // 此時(shí)字符串的所有權(quán)并沒(méi)傳遞給函數(shù),應(yīng)此該函數(shù)沒(méi)有資格釋放該字符串
可變引用雖好,但是有個(gè)注意事項(xiàng),就是同一時(shí)刻可變引用只能有一個(gè),當(dāng)存在可變引用的時(shí)候,就不能有不可變引用,但是當(dāng)可變引用不存在的時(shí)候,就可以存在數(shù)個(gè)不可變引用,例如文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-722584.html
fn main() {
let mut s = String::from("hello");
let (a, b) = (&s, &s); // 借用兩個(gè)字符串的不可變引用
println!("不可變借用a:{}, 不可變借用b:{}", a, b);
let c = &mut s; // 借用字符串的可變引用,此時(shí)前面的兩個(gè)不可變引用不再生效
c.push_str(" world");
println!("{}", c);
}
還有一個(gè)注意事項(xiàng)就是,引用的內(nèi)容必須合法,例如下面的錯(cuò)誤示范文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-722584.html
fn main() {
let s = dangle();
}
fn dangle() -> &String {
let s = String::from("hello"); // 創(chuàng)建字符串,該字符串的所有者是變量s
&s // 返回字符串的引用,但是此時(shí)字符串要已經(jīng)離開(kāi)作用域被釋放了,因此當(dāng)函數(shù)結(jié)束,這個(gè)引用將是一個(gè)非法的懸垂引用,不過(guò)還好,在rust中這種行為無(wú)法通過(guò)編譯
}
引用規(guī)則總結(jié)
- 在任意時(shí)刻只能有一個(gè)可變引用,要么只能有多個(gè)不可變引用
- 引用必須有效
到了這里,關(guān)于Rust所有權(quán)機(jī)制的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!