C++ 智能指針代碼解析
前言
如果在程序中使用new從堆分配內(nèi)存,等到不再需要時,應(yīng)使用delete將其釋放,C++引入了智能指針auto_ptr,以幫助自動完成這個過程,但是aoto_ptr也有其局限性,因此從Boost庫中又引入了三種智能指針unique_ptr shared_ptr weak_ptr。
1,aoto_ptr
// ConsoleApplication1.cpp : 定義控制臺應(yīng)用程序的入口點。 // #include "stdafx.h" #include <memory> #include <string> #include <iostream> #include <ostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { auto_ptr<string> ptr1(new string("this is ptr!")); auto_ptr<string> ptr2; ptr2 = ptr1; cout << &ptr2<<endl; cout << *ptr2 << endl; return 0; }
- output :
003AFBC0
this is ptr!
但是如果輸出的是ptr1,程序會如何呢?
#include "stdafx.h" #include <memory> #include <string> #include <iostream> #include <ostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { auto_ptr<string> ptr1(new string("this is ptr!")); auto_ptr<string> ptr2; ptr2 = ptr1; cout << &ptr1 <<endl; cout << *ptr1 << endl; #這一步程序會崩潰 return 0; }
崩潰原因: 首先ptr2 = ptr1表示ptr1將訪問的權(quán)限給了ptr2,同時意味了ptr1已經(jīng)沒有訪問字符串的權(quán)限,因此會報錯。
那如何解決這個問題呢?引入了unique_ptr
2,unique_ptr
#include "stdafx.h" #include <memory> #include <string> #include <iostream> #include <ostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { unique_ptr<string> ptr1(new string("this is unique_ptr")); unique_ptr<string> ptr2; ptr2 = ptr1; #這一步編譯器會報錯 return 0; }
unique_ptr 替代auto_ptr實現(xiàn)獨占式,可以理解成,同一時刻只能有一個unique_ptr指向給定對象,unique_ptr對象始終是關(guān)聯(lián)的原始指針的唯一所有者。無法復(fù)制unique_ptr對象,它只能移動。(這樣可以保證,不會出現(xiàn)auto_ptr那樣運行時會出現(xiàn)的隱藏內(nèi)存崩潰問題)
int _tmain(int argc, _TCHAR* argv[]) { unique_ptr<string> ptr1(new string("this is unique_ptr")); unique_ptr<string> ptr2; cout << &ptr1 << endl; unique_ptr<string> ptr3(new string("other unique_ptr")); cout << &ptr3 << endl; cout << *ptr3 << endl; return 0; }
- output:
00D9F8B4
00D9F89C
other unique_ptr
3,share_ptr
// ConsoleApplication1.cpp : 定義控制臺應(yīng)用程序的入口點。 // #include "stdafx.h" #include <memory> #include <string> #include <iostream> #include <ostream> using namespace std; class base{ public: base() { cout << "begin..." << endl; }; ~base() { cout << "end..." << endl; } }; int _tmain(int argc, _TCHAR* argv[]) { base *a = new base(); shared_ptr<base> ptr1(a); //shared_ptr<base> ptr2(a); ## 如果加上這句程序會崩潰,雙重管理陷阱,a對象被刪除了兩次 return 0; }
- output:
begin...
end...
- share_ptr的循環(huán)陷阱
#include "stdafx.h" #include <memory> #include <string> #include <iostream> #include <ostream> using namespace std; class CB; class CA { public: CA() { cout << "CA call ..."<< endl; } ~CA() { cout << "~CA call..."<< endl; } void setPtr(shared_ptr<CB> &ptr) { m_ptr_b = ptr; } int getCount() { return m_ptr_b.use_count(); } private: shared_ptr<CB> m_ptr_b; }; class CB { public: CB() { cout << "CB call..." << endl; } ~CB() { cout << "~CB call..." << endl; } void setPtr(shared_ptr<CA> ptr) { m_ptr_a = ptr; } int getCount() { return m_ptr_a.use_count(); } private: shared_ptr<CA> m_ptr_a; }; int _tmain(int argc, _TCHAR* argv[]) { shared_ptr<CA> ptr_a(new CA); shared_ptr<CB> ptr_b(new CB); cout << " CA count is : " << ptr_a->getCount()<<endl; cout << "CB count is:" << ptr_b->getCount()<< endl; ptr_a->setPtr(ptr_b); ptr_b->setPtr(ptr_a); cout << " CA count is : " << ptr_a->getCount() << endl; cout << "CB count is:" << ptr_b->getCount() << endl; return 0; }
上面這段程序的思路用下面張圖可以清晰的表示
圖片和代碼主要參考的是這篇很棒的博文:智能指針(三):weak_ptr淺析
運行結(jié)果后發(fā)現(xiàn)并沒有調(diào)用析構(gòu)函數(shù)釋放內(nèi)存,以后存在內(nèi)存泄漏的風(fēng)險
那如何去解決這個問題呢?,可以通過引入weak_ptr來解決,但是weak_ptr需要與share_ptr配合使用
4, weak_ptr
通過在兩個類中的一個成員變量改為weak_ptr對象,因為weak_ptr不會增加引用計數(shù),使得引用形不成環(huán),最后就可以正常的釋放內(nèi)部的對象,不會造成內(nèi)存泄漏
class CB { public: CB() { cout << "CB call..." << endl; } ~CB() { cout << "~CB call..." << endl; } void setPtr(shared_ptr<CA> ptr) { m_ptr_a = ptr; } int getCount() { return m_ptr_a.use_count(); } private: ///shared_ptr<CA> m_ptr_a; weak_ptr<CA> m_ptr_a; ## 改為weak_ptr對象 };
總結(jié)
遇到這類新的概念或者方法時,一定要不嫌麻煩的一行一行代碼的去敲,在敲的過程中去理解吸收,如果只看不實踐,很有可能理解不深刻,無法體會到其中的原理和機(jī)制,所以對待問題一定要沉下心來多實踐。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
win10環(huán)境下C++ vs2015編譯opencv249的教程
這篇文章主要介紹了win10環(huán)境下C++ vs2015編譯opencv249的教程,本文分步驟給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03C++中的多態(tài)與虛函數(shù)的內(nèi)部實現(xiàn)方法
下面小編就為大家?guī)硪黄狢++中的多態(tài)與虛函數(shù)的內(nèi)部實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12利用C++開發(fā)一個protobuf動態(tài)解析工具
數(shù)據(jù)庫中存儲的protobuf序列化的內(nèi)容,有時候查問題想直接解析查看內(nèi)容。很多編碼在網(wǎng)上很容易找到編解碼工具,但protobuf沒有找到編解碼工具,可能這樣的需求比較少吧,那就自己用C++實現(xiàn)一個,感興趣的可以了解一下2023-01-01C語言 哈希查找詳解(哈希表的創(chuàng)建、處理沖突、查找等)
哈希表是一種非常重要的數(shù)據(jù)結(jié)構(gòu),并在大量的計算機(jī)科學(xué)和工程應(yīng)用中發(fā)揮重要作用,了解哈希表的原理和實現(xiàn)方式,將有助于我們更好地理解這個數(shù)據(jù)結(jié)構(gòu)及如何應(yīng)用它來解決實際問題,這篇文章主要介紹了C語言 哈希查找(哈希表的創(chuàng)建、處理沖突、查找等),需要的朋友可以參考下2024-01-01