開(kāi)發(fā)人員在管理堆或棧上的數(shù)據(jù)時(shí)可以使用傳統(tǒng)的指針。但是,這些傳統(tǒng)的使用的指針?lè)椒ㄓ泻芏嗳秉c(diǎn),比如動(dòng)態(tài)分配的對(duì)象沒(méi)有及時(shí)進(jìn)行內(nèi)存釋放時(shí),會(huì)導(dǎo)致內(nèi)存泄漏。好消息是,有更好的內(nèi)存管理方法可以自動(dòng)處理內(nèi)存釋放,而且還不需要運(yùn)行時(shí)成本,它們被稱為智能指針。 Rust是一種開(kāi)源、底層、面向?qū)ο蠛挽o態(tài)類型的編程語(yǔ)言,具有高效的內(nèi)存管理,確保了高性能和安全性。它能夠用來(lái)構(gòu)建高性能,高安全和健壯的應(yīng)用程序,包括web、移動(dòng)、游戲和網(wǎng)絡(luò)應(yīng)用程序。 本文將讓你了解什么是智能指針、它們的用例以及它們?cè)赗ust中的實(shí)現(xiàn)。所包含的代碼示例將向你介紹Rust各種類型的智能指針。 什么是智能指針? 智能指針是抽象數(shù)據(jù)類型,在編程中與常規(guī)指針(存儲(chǔ)值的內(nèi)存地址的變量)的作用類似,并附加了析構(gòu)函數(shù)和重載操作符等附加功能。它們還包括自動(dòng)內(nèi)存管理,以解決內(nèi)存泄漏等問(wèn)題。 當(dāng)開(kāi)發(fā)人員將包含動(dòng)態(tài)分配數(shù)據(jù)的內(nèi)存與智能指針鏈接起來(lái)時(shí),它們將被自動(dòng)清理。 自動(dòng)取消分配數(shù)據(jù)和銷毀對(duì)象 檢查超出邊界的數(shù)據(jù)或變量 減少與使用常規(guī)指針相關(guān)的錯(cuò)誤 在取消數(shù)據(jù)分配后,保持程序的效率 跟蹤程序數(shù)據(jù)/對(duì)象/變量的所有內(nèi)存地址 在程序應(yīng)用程序中管理網(wǎng)絡(luò)連接
Rust通過(guò)一個(gè)稱為所有權(quán)的系統(tǒng)(或一組規(guī)則)實(shí)現(xiàn)內(nèi)存管理,所有權(quán)包含在應(yīng)用程序中,并在程序成功編譯前由編譯器檢查,而不會(huì)導(dǎo)致任何停機(jī)。 通過(guò)使用struct,Rust執(zhí)行智能指針。在前面提到的智能指針的附加功能中,它們還具有擁有值本身的功能。 接下來(lái),你將了解一些有助于在Rust中自定義智能指針操作的特征。 Deref trait用于有效的解引用,從而可以輕松訪問(wèn)存儲(chǔ)在智能指針后面的數(shù)據(jù)??梢允褂肈eref trait將智能指針作為引用。 Drop trait類似于Deref trait,但用于解構(gòu),Rust通過(guò)清理程序不再使用的資源來(lái)自動(dòng)實(shí)現(xiàn)解構(gòu)。因此,Drop trait用于釋放該值所占用的內(nèi)存空間。 要使用Drop trait,你需要實(shí)現(xiàn)drop()方法,它帶有一個(gè)可變引用,用于對(duì)不再需要或超出范圍的值執(zhí)行銷毀,定義為:為了更好地理解Drop trait是如何工作的,請(qǐng)看下面的例子: 1struct Consensus { 2 small_town: i32 3} 4 5impl Drop for Consensus { 6 fn drop(&mut self) { 7 println!('This instance of Consensus has being dropped: {}', self.small_town); 8 } 9} 10 11fn main() { 12 let _first_instance = Consensus{small_town: 10}; 13 let _second_instance = Consensus{small_town: 8}; 14 15 println!('Created instances of Consensus'); 16}
Drop trait的drop()方法和可變引用,是通過(guò)在struct上使用impl關(guān)鍵字實(shí)現(xiàn)的。當(dāng)main()函數(shù)中的實(shí)例超出作用域時(shí)調(diào)用drop方法,打印語(yǔ)句到控制臺(tái)。Created instances of Consensus This instance of Consensus has being dropped: 8 This instance of Consensus has being dropped: 10 Rust中存在很多種類型的智能指針。在這里將通過(guò)代碼示例了解其中一些類型及其用例。它們包括:Rc<T>表示引用計(jì)數(shù)智能指針類型。在Rust中,每個(gè)值每次都有一個(gè)所有者,而一個(gè)值有多個(gè)所有者是違反所有權(quán)規(guī)則的。然而,Reference counting智能指針類型保存代碼中每個(gè)變量的引用計(jì)數(shù)。當(dāng)引用的計(jì)數(shù)返回零時(shí),它們不再被使用,智能指針將清理它們。 在下面的示例中,將創(chuàng)建三個(gè)列表。第一個(gè)列表將有兩個(gè)值,第二個(gè)和第三個(gè)列表將使用第一個(gè)列表作為它們的第二個(gè)值。這意味著后兩個(gè)列表將與第一個(gè)列表共享所有權(quán): 1use std::rc::Rc; 2 3enum List { 4 Cons(i32, Rc<List>), Nil, 5} 6 7use List::{Cons, Nil}; 8 9fn main() { 10 let _first_list = Rc::new(Cons(10, Rc::new(Cons(20, Rc::new(Nil))))); 11 println!('The count after creating _first_list is {}', Rc::strong_count(&_first_list)); 12 13 let _second_list = Cons(8, Rc::clone(&_first_list)); 14 println!('The count after creating _second_list is {}', Rc::strong_count(&_first_list)); 15 16 { 17 let _third_list = Cons(9, Rc::clone(&_first_list)); 18 println!('The count after creating _third_list is {}', Rc::strong_count(&_first_list)); 19 } 20 21 println!('The count after _third_list goes out of scope is {}', Rc::strong_count(&_first_list)); 22}
The count after creating _first_list is 1 The count after creating _second_list is 2 The count after creating _third_list is 3 The count after _third_list goes out of scope is 2 Box<T>智能指針將值存儲(chǔ)在堆中,<T>表示數(shù)據(jù)類型。例子如下:1fn main() { 2 let stack_data = 20; 3 let hp_data = Box::new(stack_data); // points to the data in the heap 4 println!('hp_data = {}', hp_data); // output will be 20. 5}
stack_data值存儲(chǔ)在堆中 Box智能指針hp_data存儲(chǔ)在棧中 RefCell<T>是一種智能指針類型,它在運(yùn)行時(shí)而不是編譯時(shí)執(zhí)行借用規(guī)則。使用RefCell<T>,可在運(yùn)行時(shí)檢查可變和不可變借用。因此,如果你的代碼中有幾個(gè)不可變引用的數(shù)據(jù),使用RefCell<T>,就可以更改數(shù)據(jù)。 1#[derive(Debug)] 2enum List { 3 Cons(Rc<RefCell<i32>>, Rc<List>), Nil, 4} 5 6use List::{Cons, Nil}; 7use std::cell::RefCell; 8use std::rc::Rc; 9 10fn main() { 11 let data = Rc::new(RefCell::new(10)); 12 13 let _first_list = Rc::new(Cons(Rc::clone(&data), Rc::new(Nil))); 14 15 let _second_list = Cons(Rc::new(RefCell::new(9)), Rc::clone(&_first_list)); 16 17 let _third_list = Cons(Rc::new(RefCell::new(10)), Rc::clone(&_first_list)); 18 19 *data.borrow_mut() += 20; 20 21 println!('first list after = {:?}', _first_list); 22 println!('second list after = {:?}', _second_list); 23 println!('third list after = {:?}', _third_list); 24}
創(chuàng)建了Rc<RefCell<i32>>類型的數(shù)據(jù) 創(chuàng)建了與data具有共享所有權(quán)的_first_list 創(chuàng)建另外兩個(gè)與_first_list共享所有權(quán)的列表,_second_list和_third_list。 在data上調(diào)用borrow_mut()函數(shù)(該函數(shù)返回RefMut<T>智能指針),并使用解引用操作符*來(lái)解引用Rc<T>,從RefCell獲得內(nèi)部值,并更改該值。
first list after = Cons(RefCell { value: 30 }, Nil) second list after = Cons(RefCell { value: 9 }, Cons(RefCell { value: 30 }, Nil)) third list after = Cons(RefCell { value: 10 }, Cons(RefCell { value: 30 }, Nil))
https://blog./smart-pointers-rust/
|