本系列文章是Jon Gjengset發布的CRust of Rust系列視頻的學習筆記,CRust of Rust是一系列持續更新的Rust中級教程。
我們將通過手動實現Cell
新建一個項目:
cargo new --lib pointers手動實現Cell
1modcell;在cell.rs中寫入如下代碼:
1usestd::UnsafeCell; 2 3pubstructCell{ 4value:UnsafeCell , 5} 6 7impl Cell { 8pubfnnew(value:T)->Self{ 9Cell{ 10value:UnsafeCell::new(value), 11} 12} 13 14pubfnset(&self,value:T){ 15unsafe{ 16*self.value.get()=value 17}; 18} 19 20pubfnget(&self)->TwhereT:Copy{ 21unsafe{ 22*self.value.get() 23} 24} 25}
實現內部可變性需要一個特殊的cell類型,叫作UnsafeCell
在set和get方法中需要獲取類型的原生的指針,因此需要使用unsafe塊。由于UnsafeCell實現了!Sync trait,表示不能安全的跨線程共享引用。
測試代碼如下:
1#[cfg(test)] 2modtest{ 3usesuper::Cell; 4 5#[test] 6fncell_test(){ 7letmutx=Cell::new(42); 8leti=x.get(); 9x.set(43); 10 11assert_eq!(i,42); 12} 13}執行cargo test,測試通過。 手動實現RefCell
RefCell
在src目錄下新建一個refcell.rs文件,然后在lib.rs中加入:
1modrefcell;在refcell.rs中寫入如下代碼:
1usestd::UnsafeCell; 2usecrate::Cell; 3 4#[derive(Clone,Copy)] 5enumRefState{ 6Unshared, 7Shared(usize), 8Exclusive, 9} 10 11pubstructRefCell{ 12value:UnsafeCell , 13state:Cell , 14} 15 16impl RefCell { 17pubfnnew(value:T)->Self{ 18Self{ 19value:UnsafeCell::new(value), 20state:Cell::new(RefState::Unshared), 21} 22} 23 24pubfnborrow(&self)->Option<&T>{ 25None 26} 27 28pubfnborrow_mut(&self)->Option<&mut?T>{ 29None 30} 31}
這是RefCell
RecCell
引用狀態我們使用了上面剛完成的Cell進行包裝,是因為需要使用內部可變性來改變狀態。
下面來完成borrow和borrow_mut方法:
1pubfnborrow(&self)->Option<&T>{ 2matchself.state.get(){ 3//當前狀態如果是非共享狀態,則設置引用狀態為共享狀態 4RefState::Unshared=>{ 5self.state.set(RefState::Shared(1)); 6Some(unsafe{&*self.value.get()}) 7}, 8//當前狀態如果是共享狀態,則引用計數加1 9RefState::Shared(n)=>{ 10self.state.set(RefState::Shared(n+1)); 11Some(unsafe{&*self.value.get()}) 12}, 13//當前狀態如果是獨占狀態,則返回None 14RefState::Exclusive=>None, 15} 16} 17 18pubfnborrow_mut(&self)->Option<&mut?T>{ 19//引用狀態既不是共享狀態,也不是獨占狀態,才能設置為獨占狀態。 20ifletRefState::Unshared=self.state.get(){ 21self.state.set(RefState::Exclusive); 22Some(unsafe{&mut*self.value.get()}) 23}else{ 24None 25} 26}現在有個問題,共享狀態的引用計數只有增沒有減,下面增加兩個類型來完善RefCell
1/** 2*包裝RefCell的共享引用struct 3*/ 4pubstructRef<'refcell,?T>{ 5refcell:&'refcellRefCell , 6} 7 8impl DropforRef<'_,?T>{ 9//超出作用域范圍時,共享引用狀態的變化 10fndrop(&mutself){ 11matchself.refcell.state.get(){ 12RefState::Unshared|RefState::Exclusive=>unreachable!(), 13RefState::Shared(1)=>{ 14self.refcell.state.set(RefState::Unshared); 15}, 16RefState::Shared(n)=>{ 17self.refcell.state.set(RefState::Shared(n-1)); 18} 19} 20} 21} 22 23impl std::DerefforRef<'_,?T>{ 24typeTarget=T; 25 26//解引用時直接返回T的引用 27fnderef(&self)->&Self::Target{ 28unsafe{&*self.refcell.value.get()} 29} 30}
1/** 2*包裝RefCellRefCell的可變引用struct 3*/ 4pubstructRefMut<'refcell,?T>{ 5refcell:&'refcellRefCell , 6} 7 8impl DropforRefMut<'_,?T>{ 9//超出作用域范圍時,獨占引用狀態的變化 10fndrop(&mutself){ 11matchself.refcell.state.get(){ 12RefState::Unshared|RefState::Shared(_)=>unreachable!(), 13RefState::Exclusive=>{ 14self.refcell.state.set(RefState::Unshared); 15} 16} 17} 18} 19 20impl std::DerefforRefMut<'_,?T>{ 21typeTarget=T; 22 23//解引用時直接返回T的引用 24fnderef(&self)->&Self::Target{ 25unsafe{&*self.refcell.value.get()} 26} 27} 28 29impl std::DerefMutforRefMut<'_,?T>{ 30//解引用時直接返回T的可變引用 31fnderef_mut(&mutself)->&mutSelf::Target{ 32unsafe{&mut*self.refcell.value.get()} 33} 34}
1pubfnborrow(&self)->Option>{ 2matchself.state.get(){ 3//當前狀態如果是非共享狀態,則設置引用狀態為共享狀態 4RefState::Unshared=>{ 5self.state.set(RefState::Shared(1)); 6Some(Ref{refcell:self}) 7}, 8//當前狀態如果是共享狀態,則引用計數加1 9RefState::Shared(n)=>{ 10self.state.set(RefState::Shared(n+1)); 11Some(Ref{refcell:self}) 12}, 13//當前狀態如果是獨占狀態,則返回None 14RefState::Exclusive=>None, 15} 16} 17 18pubfnborrow_mut(&self)->Option通過我們自己實現的Cell>{ 19//引用狀態既不是共享狀態,也不是獨占狀態,才能設置為獨占狀態。 20ifletRefState::Unshared=self.state.get(){ 21self.state.set(RefState::Exclusive); 22Some(RefMut{refcell:self}) 23}else{ 24None 25} 26}
-
計數器
+關注
關注
32文章
2283瀏覽量
95832 -
文件
+關注
關注
1文章
577瀏覽量
25126 -
指針
+關注
關注
1文章
484瀏覽量
70910 -
代碼
+關注
關注
30文章
4880瀏覽量
70004 -
Rust
+關注
關注
1文章
233瀏覽量
6887
原文標題:CRust學習筆記:智能指針和內部可變性
文章出處:【微信號:Rust語言中文社區,微信公眾號:Rust語言中文社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
Windows -編程-變量和可變性
Windows -編程-變量和可變性-陰影
CRust學習筆記:生命周期-1
CRust學習筆記:生命周期-2
CRust學習筆記:聲明宏
python字符串序列操作和不可變性
rust語言基礎學習: 智能指針之Cow
面對不斷增加的設計可變性,提高穩健性并最大限度地減少過度悲觀情緒

C++智能指針的底層實現原理

評論