<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
使用區域性物件來管理資源的技術
RAII的原理
delete後的指標變數就變成了一個失效指標(也叫作懸空指標)。
對於下面的程式碼:
void Destroy(Object *op) { delete op; delete[] op; } Object *op = new Object(10); Object *arop = new Object[10]; Destroy(op); Destroy(arop);
因此:
智慧指標是比原始指標更加智慧的類,解決懸空指標多次刪除被指向物件,以及資源洩漏問題,通常用來確保指標的壽命和其指向物件的壽命一致。
智慧指標雖然很智慧,很容易被誤用,智慧也是有代價的。
auto_ptr
unqiue_ptr
(唯一性智慧指標)shared_ptr
(共用性智慧指標)weak_ptr
(管理弱參照)其中後三個是C11支援,並且第一個已經被C11棄用。
C98中的auto_ptr
所做的事情,就是動態分配物件以及當物件不再需要時自動執行清理。
下面我們首先來了解一下為什麼要將auto_ptr移除的原因:
因為該型別的智慧指標意義不明確,使用淺拷貝方式時,兩個物件擁有同一塊資源:我們模仿原始碼的邏輯
瞭解一下:比如下面的程式碼:
class Object { int value; public: Object(int x = 0):value(x){cout<<"Create Object:"<<this<<endl;} ~Object(){cout<<"Destroy Object:"<<this<<endl;} int & Value(){return value;} const int& Value() const{return value;} }; template<class _Ty> class my_auto_ptr { private: bool _Owns;//所有權 _Ty* _Ptr; public: my_auto_ptr(_Ty* p = NULL):_Owns(p != NULL),_Ptr(p){} ~my_auto_ptr() { if(_Owns) { delete _Ptr; } _Owns = false; _Ptr = NULL; } _Ty* get() const { return _Ptr; } _Ty* operator->()const { return get(); } _Ty & operator*() { return *get(); } void reset(_Ty* p = NULL) { if(_Owns) { delete _Ptr; } _Ptr = p; } _Ty * release()const//編譯要通過,要麼異變,要麼強轉成普通指標 { _Ty* tmp = NULL; if(_Owns) { ((my_auto_ptr*)this)->_Owns = false; tmp = _Ptr; ((my_auto_ptr*)this)->_Ptr = NULL; } return tmp; } my_auto_ptr(const my_auto_ptr & op):_Owns(op._Owns) { if(_Owns) { _Ptr = op._Ptr; } } }; void fun() { my_auto_ptr<Object> pobj(new Object(10));//pobj是my_auto_ptr型別 cout<<pobj->Value()<<endl; cout<<(*pobj).Value()<<endl;//(*pobj)是Object的堆區物件。*(pobj._Ptr).Value() } int main() { my_auto_ptr<Object> pobja(new Object(10)); my_auto_ptr<Object> pobjb(pobja); }
相關函數解釋:
此時程式必然會導致程式崩潰引發異常,主函數結束時對同一部分資源釋放了兩次,堆記憶體被釋放兩次
那麼我們可能會考慮,將資源轉移,即修改拷貝構造如下:利用是釋放函數
my_auto_ptr(const my_auto_ptr & op):_Owns(op._Owns),_Ptr(op.release()) {}
看似好像解決了上面的問題,實則存在隱患
繼續來看:下面的程式碼存在什麼問題呢?
void fun(my_auto_ptr<Object> apx) { int x = apx->Value(); cout<<x<<endl; } int main() { my_auto_ptr<Object> pobja(new Object(10)); fun(pobja); int a = pobja->Value(); cout<<a<<endl; }
上述程式碼的執行邏輯如下:
pobja
有兩個域擁有權域和指標域,拿pobja初始化形參apx時,會調動拷貝建構函式apx
將自己的擁有權域設為1,調動release函數,銷燬了pobja物件的資源後,返回堆區物件的地址,apx接收後將自身的指標域指向原先pobja所指向的堆區物件fun
函數結束,apx區域性物件就會被解構,此時再列印a,物件其實已經不存在了並且自身早已失去了pobja的擁有權。綜上,此時智慧指標的拷貝建構函式的兩種寫法:
my_auto_ptr(const my_auto_ptr & op):_Owns(op._Owns) { if(_Owns) { _Ptr = op._Ptr; } } my_auto_ptr(const my_auto_ptr & op):_Owns(op._Owns),_Ptr(op.release()) {}
因此,C11標準之前的auto_ptr
這個智慧指標不被廣泛使用的原因就是:在某些應用場景下,拷貝建構函式的意義不明確,同理賦值語句也是這個道理,意義同樣不明確,因為C11標準之前並不存在移動賦值和移動構造的概念,還有就是之前談到的一個物件和一組物件的問題,對於自定義型別而言,auto_ptr
的解構函式僅能夠解構一個物件,不能夠處理一組物件的情況,這些都是尚未解決的問題。
於是在C11中棄用,C17標準中直接移除。
歷史淵源:
在STL庫之前,有一個功能更加強大的boost庫,STL為了與其抗衡,應急製造了STL,但製作的不夠完善,由此因為STL未解決auto_ptr
的問題,因此STl內的容器vector和list都不想和auto_ptr建立聯絡。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45