所有權(quán)
寫程序不可避免要管理內(nèi)存,而內(nèi)存管理是非常容易出錯(cuò)的,有的語言使用垃圾回收機(jī)制,有的靠開發(fā)者自己管理。垃圾回收會(huì)降低執(zhí)行效率,開發(fā)者自己管理對(duì)開發(fā)要求很高。Rust突破限制,使用獨(dú)有的所有權(quán)機(jī)制解決內(nèi)存管理問題。
所有權(quán)與堆棧關(guān)系密切。棧和堆使用效率是有區(qū)別的,棧是有序的,所以使用起來更快。堆是隨機(jī)存儲(chǔ)的,跳躍存取肯定要比順序存取慢。變量存入棧時(shí)必須知道大小,而堆可以不確定大小,分配一塊足夠大的內(nèi)存區(qū)域即可??墒欠峙鋾r(shí)需要尋找一塊足夠大的塊,這就要花費(fèi)些時(shí)間。
所有權(quán)有三個(gè)特點(diǎn):
每個(gè)變量都有他的所有者
所有者同時(shí)只有一個(gè)
所有者出了作用域就會(huì)釋放變量
以String為例,String大小是變化的,所以是在運(yùn)行時(shí)分配的,并且需要申請(qǐng)堆內(nèi)存,堆內(nèi)存的申請(qǐng)是通過from方法,申請(qǐng)之后的釋放往往是關(guān)鍵。有些語言通過gc控制,自動(dòng)回收;有些沒有g(shù)c的語言需要手動(dòng)釋放;rust則是通過在作用域結(jié)束自動(dòng)調(diào)用drop方法來釋放的。
Move:
下面的代碼中x和y的值都是5,而且都存儲(chǔ)在棧上,實(shí)際上是棧上有兩個(gè)5,y=x的時(shí)候復(fù)制了一個(gè)到棧上,所以有兩個(gè),而不是同時(shí)指向一個(gè)。
對(duì)于復(fù)雜類型,也就是數(shù)據(jù)存儲(chǔ)在堆中的類型,復(fù)制的只是棧上的內(nèi)容,并不復(fù)制堆中的內(nèi)容。
s1在棧中存儲(chǔ)了指向堆的指針、字符串長(zhǎng)度和可存儲(chǔ)容量。賦值時(shí),s2復(fù)制了s1的棧信息,指向與s1相同的堆內(nèi)存,然后s1會(huì)失效。相當(dāng)于將堆內(nèi)存從s1移動(dòng)到了s2,所以賦值操作稱為移動(dòng)。移動(dòng)=淺拷貝+失效舊變量。
如果想要實(shí)現(xiàn)深拷貝,也就是堆數(shù)據(jù)也被拷貝,則使用clone方法即可。
標(biāo)量類型,占用的內(nèi)存大小是確定的,存儲(chǔ)在棧中的,默認(rèn)都是實(shí)現(xiàn)了clone特性的,深拷貝與淺拷貝是相同的。包含標(biāo)量類型的tuple默認(rèn)也實(shí)現(xiàn)了clone,如(i32, i32)實(shí)現(xiàn)了,(i32, String)沒實(shí)現(xiàn)。
實(shí)現(xiàn)了drop特性的類型不能再實(shí)現(xiàn)clone。
對(duì)于函數(shù)的入?yún)⒑头祷貐?shù)都是和賦值操作類似的,也會(huì)有變量的move操作。
當(dāng)堆中的變量離開作用域時(shí),會(huì)調(diào)用drop,但是如果變量move了,失去了所有權(quán)就不會(huì)調(diào)drop了。
如果除了返回move參數(shù)外,想返回多個(gè)附加數(shù)據(jù),那么一種方法是可以用tuple來傳遞。