1、所有權(quán)的概念:
程序需要管理自己在運(yùn)行時(shí)使用的計(jì)算機(jī)內(nèi)部空間。Rust語(yǔ)言采用包含特定規(guī)則的所有權(quán)系統(tǒng)來(lái)管理內(nèi)存,這套規(guī)則允許編譯器在編譯的過(guò)程中執(zhí)行檢查工作,而不會(huì)產(chǎn)生任何的運(yùn)行時(shí)開銷。
(1)、所有權(quán)規(guī)則:
- Rust中的每一個(gè)值都有一個(gè)對(duì)應(yīng)的變量作為它的所有者;
- 在同一時(shí)間內(nèi),值有且僅有一個(gè)所有者;
- 當(dāng)所有者離開自己的作用域時(shí),它持有的值就會(huì)被釋放掉。
(2)、變量的作用域:
作用域是指一個(gè)對(duì)象在程序中的有效范圍。
變量的有效范圍說(shuō)明:
{//S未被聲明,在這里還不可用
let s = "hello";//從這里開始S變得可用
//執(zhí)行與S相關(guān)的操作
}//作用域到這兒結(jié)束,變量S再次不可用
2、String類型:
String類型的數(shù)據(jù)存放在堆上,是一個(gè)可變的字符串類型。Rust在變量結(jié)束的地方會(huì)自動(dòng)調(diào)用drop函數(shù),String類型的作者在drop函數(shù)中編寫了自動(dòng)釋放內(nèi)存的程序。
注意:任何簡(jiǎn)單的標(biāo)量的組合類型都是可以Copy的,任何需要分配內(nèi)存或某種資源的類型都不會(huì)是Copy的。下面是一些擁有Copy這種trait的類型:
- 所有的整數(shù)類型;
- 僅擁有兩種值的布爾類型;
- 字符類型;
- 所有的浮點(diǎn)類型;
- 如果元組所包含的所有字段的類型都是Copy的,那么這個(gè)元組也是Copy的。
3、所有權(quán)與函數(shù):
將值傳遞給函數(shù)在語(yǔ)義上類似于對(duì)變量進(jìn)行賦值。將變量傳遞給函數(shù)將會(huì)觸發(fā)移動(dòng)或復(fù)制,就像賦值語(yǔ)句一樣。
fn main()
{
let s = String::from("hello");//變量s進(jìn)入作用域
takes_owership(s);//s的值被移動(dòng)進(jìn)了函數(shù)
//s的值在這里不再有效
let x = 5;//x進(jìn)入作用域
make_copy(x);//x的值被傳遞進(jìn)了函數(shù)
//由于i32是Copy的,所以在這兒依舊可以使用x
}//x的值首先離開作用域,隨后是s
//由于s已經(jīng)發(fā)生了移動(dòng),所以不會(huì)發(fā)生什么情況
fn takes_owership(some_string:String){//s進(jìn)入作用域
println!("{}",some_string);
}//some_string在這里離開作用域,drop函數(shù)被自動(dòng)調(diào)用
//some_string所占用的內(nèi)存被釋放
fn make_copy(some_integer:i32){//some_integer進(jìn)入作用域
println!("{}",some_integer);
}//some_integer在這里離開作用域,沒(méi)有什么發(fā)生
4、返回值與作用域:
函數(shù)在返回值的過(guò)程中也會(huì)發(fā)生所有權(quán)的轉(zhuǎn)移。
變量所有權(quán)的轉(zhuǎn)移總會(huì)遵循相同的模式:將一個(gè)變量賦值給另一個(gè)變量時(shí)就會(huì)轉(zhuǎn)移所有權(quán)。當(dāng)一個(gè)持有堆數(shù)據(jù)的變量離開作用域時(shí),它的數(shù)據(jù)就會(huì)被drop清理回收,除非這些數(shù)據(jù)的所有權(quán)轉(zhuǎn)移到了另一個(gè)變量上。
5、引用與借用:
引用是指在不獲取所有權(quán)的前提下使用某個(gè)變量的值。
示例:
fn main(){
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{}'is {}.",s1,len);
}
fn calculate_length -> usize{
s.len()
}
在調(diào)用calculate_length函數(shù)時(shí)使用了&s1
作為參數(shù),并且在該函數(shù)的定義中,使用&String替代了String。
其中&
代表的就是引用的語(yǔ)義。
由于引用并不持有值的所有權(quán),所以當(dāng)引用離開當(dāng)前作用域的時(shí)候,它指向的值也不會(huì)被丟棄,同樣也不能對(duì)引用值進(jìn)行更改。
這種通過(guò)引用傳遞參數(shù)給函數(shù)的方法也被稱為借用。
6、可變引用:
將變量聲明為mut s
,再使用&mut s
給函數(shù)傳遞一個(gè)可變引用,并將函數(shù)簽名改為some_string:&mut String
來(lái)使其接收一個(gè)可變引用作為參數(shù)。
可變引用在使用上有一個(gè)限制:對(duì)于特定作用域中的特定數(shù)值來(lái)說(shuō),一次只能聲明一個(gè)可變引用。以下示例違背了這條規(guī)則:
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
Rust中的這一限定性規(guī)則可以幫助在編譯時(shí)避免數(shù)據(jù)競(jìng)爭(zhēng)。數(shù)據(jù)競(jìng)爭(zhēng)與競(jìng)態(tài)條件十分相似,它會(huì)在滿足以下三種情況時(shí)發(fā)生:
- 兩個(gè)或兩個(gè)以上的指針同時(shí)訪問(wèn)同一空間;
- 其中至少有一個(gè)指針會(huì)向空間中寫入數(shù)據(jù);
- 沒(méi)有同步數(shù)據(jù)訪問(wèn)的機(jī)制。
數(shù)據(jù)競(jìng)爭(zhēng)會(huì)導(dǎo)致未定義行為,這些未定義行為會(huì)使得出現(xiàn)的bug難以被修復(fù)和診斷。
7、懸垂引用:
懸垂指針指向曾經(jīng)存在的某處內(nèi)存地址,但該內(nèi)存已近被釋放甚至是被重新分配另作他用了。
8、切片:
切片允許我們引用集合中某一段連續(xù)的元素序列,而不是整個(gè)集合。
(1)、字符串切片:
字符串切片是指向String對(duì)象中某個(gè)連續(xù)部分的引用,它使用方式如下:
let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];
使用方括號(hào)中指定切片的范圍區(qū)間[starting_index..ending_index]
,其中starting_index
是切片起始位置的索引值,ending_index
是切片終止位置的下一個(gè)索引值。切片數(shù)據(jù)結(jié)構(gòu)在內(nèi)部存儲(chǔ)了指向起始位置的引用和一個(gè)描述切片長(zhǎng)度的字段,這個(gè)描述切片長(zhǎng)度的字段等價(jià)于ending_index
減去starting_index
。
注:當(dāng)范圍是從第一個(gè)元素開始時(shí),可以省略兩個(gè)點(diǎn)號(hào)之前的值;當(dāng)切片包含String中的最后一個(gè)字節(jié)時(shí),可以省略雙點(diǎn)號(hào)之后的值。
(2)、其它類型的切片:
字符串切片是專門用來(lái)處理字符串的,除此之外,Rust還存在其他更為通用的切片類型,以數(shù)組為例:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-601887.html
let a = [1,2,3,4,5];
let slice = &a[1..3];
這與字符串切片的工作機(jī)制完全一樣。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-601887.html
到了這里,關(guān)于Rust之所有權(quán)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!