您好,登錄后才能下訂單哦!
所謂智能指針就是自動化管理指針所指向的動態(tài)資源的釋放。
那么智能指針的引用是為了解決哪些問題呢?
代碼中經(jīng)常會忘掉釋放動態(tài)開辟的資源,引用智能指針可用于動態(tài)資源管理,資源分配即初始化,定義一個類來封裝資源的分配和釋放,在構(gòu)造函數(shù)中完成資源的分配和初始化,在析構(gòu)函數(shù)完成資源的清理,可以保證資源的正確初始化和釋放。
智能指針的原理:智能指針是一個類,這個類的構(gòu)造函數(shù)中傳入一個普通指針,析構(gòu)函數(shù)中釋放傳入的指針。智能指針的類是棧上的對象,智能指針指向堆上開辟的空間,函數(shù)結(jié)束時,棧上的函數(shù)會自動被釋放,智能指針指向的內(nèi)存也會隨之消失,防止內(nèi)存泄漏。
智能指針的實現(xiàn)需要實現(xiàn)構(gòu)造、析構(gòu)、拷貝構(gòu)造、操作符重載。
幾種常見的智能指針的區(qū)別?
auto_ptr:就是內(nèi)部使用一個成員變量指向一塊內(nèi)存資源(構(gòu)造函數(shù)),并且在析構(gòu)函數(shù)中釋放內(nèi)存資源。auto_ptr的拷貝構(gòu)造和賦值操作符重載函數(shù)所接受的參數(shù)都是非const的引用類型(即我們可以且修改資源),不能共享所有權(quán)(其它任意一個指針指向這塊內(nèi)存,它會把內(nèi)存給別的指針,自己不指向了)。權(quán)限轉(zhuǎn)移。
template <typename T> class Auto_Ptr { public: Auto_Ptr(T *ptr = NULL) :_ptr(ptr) {} ~Auto_Ptr() { if (_ptr != NULL) { delete _ptr; cout<<"~Auto_Ptr()"<<endl; } } Auto_Ptr(Auto_Ptr<T> &ap) :_ptr(ap._ptr) { ap._ptr = NULL; } Auto_Ptr<T> &operator= (Auto_Ptr<T> &ap) { if (this != &ap) { delete _ptr; _ptr = ap._ptr; ap._ptr = NULL; } return *this; } private: T *_ptr; }; void Test1() { Auto_Ptr<int> a1(new int(1)); Auto_Ptr<int> a2(a1); Auto_Ptr<int> a3(new int(2)); a1 = a1; a2 = a3; }
scoped_ptr有著與auto_ptr類似的特性,scoped_ptr與auto_ptr最大的區(qū)別主要在于對內(nèi)存資源擁有權(quán)的處理。(auto_ptr在拷貝構(gòu)造時會從源auto_ptr自動交出擁有權(quán),而scoped_ptr則不允許被拷貝)。scoped_ptr不能資源共享。
template <typename T> class Scoped_Ptr { public: Scoped_Ptr(T *ptr) :_ptr(ptr) {} ~Scoped_Ptr() { if (_ptr != NULL) { delete _ptr; cout<<"~Scoped_Ptr()"<<endl; } } private: Scoped_Ptr(const Scoped_Ptr<T> &sp); Scoped_Ptr<T> &operator=(const Scoped_Ptr<T> &sp); T *_ptr; }; void Test2() { Scoped_Ptr<int> s1(new int(1)); //Scoped_Ptr<int> s2(s1); Scoped_Ptr<int> s3(new int(2)); //s1 = s1; //s2 = s3; }
shared_ptr就是為了解決auto_ptr在對象所有權(quán)上的局限性,在使用引用計數(shù)的基礎(chǔ)上提供了可以共享所有權(quán)的智能指針。當新增一個shared_ptr對該對象進行管理時,就將該對象的引用計數(shù)加一,同理減少一個時,計數(shù)器減一。當該對象的引用計數(shù)器為0時,調(diào)用delete釋放其所占的內(nèi)存。
template <typename T> class Shared_Ptr { public: Shared_Ptr(T *ptr) :_ptr(ptr) ,_count(new int(1)) {} ~Shared_Ptr() { if(--(*_count) == 0) { delete _ptr; delete _count; cout<<"~Shared_Ptr()"<<endl; } (*_count)--; } Shared_Ptr(Shared_Ptr<T> &sp) :_ptr(sp._ptr) ,_count(sp._count) { (*_count)++; } Shared_Ptr<T> &operator=(Shared_Ptr<T> &sp) { if (this != &sp) { if (--(*_count) == 0) { delete _ptr; delete _count; } _ptr = sp._ptr; _count = sp._count; (*_count)++; } return *this; } private: T *_ptr; int *_count; }; void Test3() { Shared_Ptr<int> s1(new int(1)); Shared_Ptr<int> s2(s1); Shared_Ptr<int> s3(new int(2)); s1 = s1; s1 = s3; }
shared_ptr存在循環(huán)引用的問題,使用weak_ptr可以用來避免循環(huán)引用。但是weak_ptr對象引用資源時不會增加引用計數(shù),無法知道資源會不會被突然釋放,所以無法通過weak_ptr訪問資源。在訪問資源時weak_ptr必須先轉(zhuǎn)化為shared_ptr。
#include <iostream> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> using namespace std; using namespace boost; struct ListNode { shared_ptr<ListNode > _prev; shared_ptr<ListNode > _next; //weak_ptr<ListNode > _prev; //weak_ptr<ListNode > _next; ~ ListNode() { cout<<"~ListNode()" <<endl; } }; void Test () { // 循環(huán)引用問題 shared_ptr <ListNode > p1( new ListNode ()); shared_ptr <ListNode > p2( new ListNode ()); cout <<"p1->Count:" << p1. use_count()<<endl ; cout <<"p2->Count:" << p2. use_count()<<endl ; // p1節(jié)點的_next指向 p2節(jié)點 p1->_next = p2; // p2節(jié)點的_prev指向 p1節(jié)點 p2->_prev = p1; cout <<"p1->Count:" << p1. use_count ()<<endl ; cout <<"p2->Count:" << p2. use_count ()<<endl ; }
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。