開發(fā)人員在管理堆或棧上的數(shù)據(jù)時可以使用傳統(tǒng)的指針。但是,這些傳統(tǒng)的使用的指針方法有很多缺點,比如動態(tài)分配的對象沒有及時進(jìn)行內(nèi)存釋放時,會導(dǎo)致內(nèi)存泄漏。好消息是,有更好的內(nèi)存管理方法可以自動處理內(nèi)存釋放,而且還不需要運(yùn)行時成本,它們被稱為智能指針。 Rust是一種開源、底層、面向?qū)ο蠛挽o態(tài)類型的編程語言,具有高效的內(nèi)存管理,確保了高性能和安全性。它能夠用來構(gòu)建高性能,高安全和健壯的應(yīng)用程序,包括web、移動、游戲和網(wǎng)絡(luò)應(yīng)用程序。 本文將讓你了解什么是智能指針、它們的用例以及它們在Rust中的實現(xiàn)。所包含的代碼示例將向你介紹Rust各種類型的智能指針。 什么是智能指針? 智能指針是抽象數(shù)據(jù)類型,在編程中與常規(guī)指針(存儲值的內(nèi)存地址的變量)的作用類似,并附加了析構(gòu)函數(shù)和重載操作符等附加功能。它們還包括自動內(nèi)存管理,以解決內(nèi)存泄漏等問題。 當(dāng)開發(fā)人員將包含動態(tài)分配數(shù)據(jù)的內(nèi)存與智能指針鏈接起來時,它們將被自動清理。 自動取消分配數(shù)據(jù)和銷毀對象 檢查超出邊界的數(shù)據(jù)或變量 減少與使用常規(guī)指針相關(guān)的錯誤 在取消數(shù)據(jù)分配后,保持程序的效率 跟蹤程序數(shù)據(jù)/對象/變量的所有內(nèi)存地址 在程序應(yīng)用程序中管理網(wǎng)絡(luò)連接
Rust通過一個稱為所有權(quán)的系統(tǒng)(或一組規(guī)則)實現(xiàn)內(nèi)存管理,所有權(quán)包含在應(yīng)用程序中,并在程序成功編譯前由編譯器檢查,而不會導(dǎo)致任何停機(jī)。 通過使用struct,Rust執(zhí)行智能指針。在前面提到的智能指針的附加功能中,它們還具有擁有值本身的功能。 接下來,你將了解一些有助于在Rust中自定義智能指針操作的特征。 Deref trait用于有效的解引用,從而可以輕松訪問存儲在智能指針后面的數(shù)據(jù)??梢允褂肈eref trait將智能指針作為引用。 Drop trait類似于Deref trait,但用于解構(gòu),Rust通過清理程序不再使用的資源來自動實現(xiàn)解構(gòu)。因此,Drop trait用于釋放該值所占用的內(nèi)存空間。 要使用Drop trait,你需要實現(xiàn)drop()方法,它帶有一個可變引用,用于對不再需要或超出范圍的值執(zhí)行銷毀,定義為:為了更好地理解Drop trait是如何工作的,請看下面的例子: 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()方法和可變引用,是通過在struct上使用impl關(guān)鍵字實現(xiàn)的。當(dāng)main()函數(shù)中的實例超出作用域時調(diào)用drop方法,打印語句到控制臺。Created instances of Consensus This instance of Consensus has being dropped: 8 This instance of Consensus has being dropped: 10 Rust中存在很多種類型的智能指針。在這里將通過代碼示例了解其中一些類型及其用例。它們包括:Rc<T>表示引用計數(shù)智能指針類型。在Rust中,每個值每次都有一個所有者,而一個值有多個所有者是違反所有權(quán)規(guī)則的。然而,Reference counting智能指針類型保存代碼中每個變量的引用計數(shù)。當(dāng)引用的計數(shù)返回零時,它們不再被使用,智能指針將清理它們。 在下面的示例中,將創(chuàng)建三個列表。第一個列表將有兩個值,第二個和第三個列表將使用第一個列表作為它們的第二個值。這意味著后兩個列表將與第一個列表共享所有權(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>智能指針將值存儲在堆中,<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值存儲在堆中 Box智能指針hp_data存儲在棧中 RefCell<T>是一種智能指針類型,它在運(yùn)行時而不是編譯時執(zhí)行借用規(guī)則。使用RefCell<T>,可在運(yùn)行時檢查可變和不可變借用。因此,如果你的代碼中有幾個不可變引用的數(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)建另外兩個與_first_list共享所有權(quán)的列表,_second_list和_third_list。 在data上調(diào)用borrow_mut()函數(shù)(該函數(shù)返回RefMut<T>智能指針),并使用解引用操作符*來解引用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/
|