<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
RAII(Resource Acquisition Is Initialization)是由C++之父提出的,中文翻譯為資源獲取即初始化,使用區域性物件來管理資源的技術稱為資源獲取即初始化;這裡的資源主要是指作業系統中有限的東西如記憶體(heap)、網路通訊端、互斥量、檔案控制程式碼等等,區域性物件是指儲存在棧的物件,它的生命週期是由作業系統來管理的,無需人工介入
資源的使用一般經歷三個步驟:
但是資源的銷燬往往是程式設計師經常忘記的一個環節,所以程式界就想如何在程式中讓資源自動銷燬呢?解決問題的方案就是:RAII,它充分的利用了C++語言區域性物件自動銷燬的特性來控制資源的生命週期
1.難以區分指向的是單個物件還是一個陣列
2.使用完指標之後無法判斷是否應該銷燬指標,因為無法判斷指標是否”擁有“指向的物件
3.在已經確定需要銷燬指標的情況下,也無法確定是用delete關鍵字刪除,還是有其他特殊的銷燬機制,例如通過將指標傳入某個特定的銷燬函數來摧毀指標
4.即使已經確定了銷燬指標的方法,由於1的原因,仍然無法確定到底是i用delete(銷燬單個物件)還是delete[](銷燬一個陣列)
5.假設上述的問題都解決了,也很難保證在程式碼的所有路徑中(分支結構,異常導致的挑戰),有且僅有一次銷燬指標的操作;任何一條路徑遺漏都可能導致記憶體的洩露,而銷燬多次則會導致未定義行為
6.理論上沒有方法來分辨一個指標是否處於懸掛狀態
class Object { int value; public: Object(int x = 0) :value(x) { cout << "Create Object:" << this << endl; } ~Object() { cout << "Destory Object:" << this << endl; } int& Value() { 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; } }; void fun() { my_auto_ptr<Object> obj(new Object(10)); } int main() { fun(); }
在這裡將Object構建完成後,將其指標給到p,當函數結束去調動智慧指標的解構函式去釋放空間
若我們需要在fun()函數中,去呼叫Object類的方法obj->Value();
class Object { int value; public: Object(int x = 0) :value(x) { cout << "Create Object:" << this << endl; } ~Object() { cout << "Destory Object:" << this << endl; } int& Value() { 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 ->()const { return get(); } }; void fun() { my_auto_ptr<Object> obj(new Object(10)); cout << obj->Value() << endl; cout << (*obj).Value() << endl; } int main() { fun(); }
通過運運算元過載,(*obj) 後將直接指向堆區(heap)的物件實體
若我們通過一個my_auto_ptr去建立另一個my_auto_ptr
class Object { int value; public: Object(int x = 0) :value(x) { cout << "Create Object:" << this << endl; } ~Object() { cout << "Destory Object:" << this << endl; } int& Value() { 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; } my_auto_ptr(const my_auto_ptr& obj):_Owns(obj._Owns),_Ptr(obj._ptr) { } my_auto_ptr& operator=(const my_auto_ptr& _Y) { if(this == &_Y) return *this; if(_Owns) { delete _Ptr; } _Owns = _Y._Owns; _Ptr = _Y._Ptr; return 0; } _Ty* get()const { return _Ptr; } _Ty& operator*()const { return *(get()); } _Ty* operator ->()const { 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; } }; void fun() { my_auto_ptr<Object> pobja(new Object(10)); my_auto_ptr<Object> pobjb(pobja); } int main() { fun(); }
如果通過淺拷貝,則兩個指標擁有同一個資源,在解構的過程會造成資源的重複釋放導致崩潰
若設定為將其資源進行轉移
my_auto_ptr(const my_auto_ptr& obj):_Owns(obj._Owns),_Ptr(release()) { } my_auto_ptr& operator=(const my_auto_ptr& _Y) { if(this == &_Y) return *this; if(_Owns) { delete _Ptr; } _Owns = _Y._Owns; _Ptr = _Y.release(); return 0; }
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失去資源進而程式崩潰
這也就是auto_ptr的侷限性,也導致該智慧指標的幾乎沒有使用
該智慧指標屬於唯一性智慧指標,將拷貝構造刪除,也就不能將其新建另一個物件,同時也不能作為引數傳入
class Object { int value; public: Object(int x = 0) :value(x) { cout << "Create Object:" << this << endl; } ~Object() { cout << "Destory Object:" << this << endl; } int& Value() { return value; } }; int main() { std::unique_ptr<Object> pobja(new Object(10)); //std::unique_ptr<Object> pobjb(pobja); error //不允許 std::unique_ptr<Object> pobjb(std::move(pobja)); }
通過移動賦值是可以的,通過明確的概念,對其資源進行轉移
同時unique_ptr可以區分其所指向的是一個單獨空間,或者是連續的空間
struct delete_ar_object { void operator()(Object* op) { if(op == NULL) return; delete[] op; } } int main() { std::unique_ptr<Object> pobja(new Object(10)); std::unique_ptr<Object,delete_ar_object> pobjb(new Object[10]); }
在這裡如果是連續空間,會呼叫刪除連續空間的刪除器;單獨空間則使用預設刪除器
unique_ptr在編寫的時候,有多個模板類,分別對應單個物件的方案和一組物件的方案
並且可以通過智慧指標指向fopen開啟的檔案物件,而檔案物件是同fclose去進行關閉的
struct delete_file { void operator()(FILE *fp) { if(fp == NULL) return; fclose(fp); } } std::unique_ptr<FILE,delete_file> pfile(fopen("zyq.txt","w"));
這裡只需要將預設的刪除器,更改為對檔案物件的刪除器
本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注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