智慧指標--scoped_ptr shared_ptr weak_ptr
所謂智慧指標就是智慧/自動化的管理指標所指向的動態資源的釋放;
scopde_ptr--防拷貝
什麼叫做防拷貝?就是不允許一個地址空間的指標賦值給另一個指標,導致有兩個指標指向同一個地址;也就是說防拷貝能保證地址與指標是一一對應的關係;
實現方法:要拷貝,就需要通過物件來呼叫賦值運算子過載函式/拷貝建構函式,只要將這兩個成員函式私有化/保護化,就ok啦;
具體程式碼:
shared_ptr--引用計數template<class T> class ScopedePtr { public: ScopedePtr(T *ptr) :_ptr(ptr) {} ~ScopedePtr() { delete _ptr; } T* GetPtr() { return _ptr; } T& operator*() { return *_ptr; } T* operator->() { return _ptr; } protected: ScopedePtr<T>& operator=(const ScopedePtr<T> &sp); ScopedePtr(const ScopedePtr<T> &sp); protected: T *_ptr; };
允許多個指向同一塊地址;每增加一個指向該地址的指標計數器就加一;減少一個指向該地址的指標計數器減一,直到計數器的值為0的時候進行delete釋放這塊空間;
程式碼:
但是share_ptr有一個迴圈引用的問題:template<class T> class SharedPtr { SharedPtr(T * ptr) :_ptr(ptr) , _ptrCount(new int(1)) { } ~SharedPtr() { if (*_ptrCount == 0) { delete _ptr; } } T& operator*() { return *_ptr; } T* operator->() { return _ptr; } SharedPtr<T>& operator=(const SharedPtr<T>& sp) { Release(); _ptr = sp._ptr; _ptrCount = sp._ptrCount; (*_ptrCount)++; } SharedPtr(const SharedPtr<T>& sp) :_ptr(sp._ptr) { _ptrCount = sp._ptrCount; (*_ptrCount)++; } void Release() { if (*_ptrCount != 0) (*_ptrCount)--; } protected: T *_ptr; int *_ptrCount; };
當在雙向連結串列時,想要釋放p1但是p2->_prev指向p1,引用計數為1,想要釋放p1必須先釋放p2;對於p2而言想要釋放也必須先釋放p1;這就構成了迴圈引用問題,兩者都不能釋放;
weak_ptr就應運而生,專們用來輔助shared_ptr;
weak_ptr物件引用資源時不會增加引用計數,但是它能夠通過lock()方法來判斷它所管理的資源是否被釋放。另外很自然地一個問題是:既然weak_ptr不增加資源的引用計數,那麼在使用weak_ptr物件的時候,資源被突然釋放了怎麼辦呢?呵呵,答案是你根本不能直接通過weak_ptr來訪問資源。那麼如何通過weak_ptr來間接訪問資源呢?答案是:在需要訪問資源的時候weak_ptr為你生成一個shared_ptr,shared_ptr能夠保證在shared_ptr沒有被釋放之前,其所管理的資源是不會被釋放的。建立shared_ptr的方法就是lock()方法。
弱指標當引用的物件活著的時候不一定存在。僅僅是當它存在的時候的一個引用。弱指標並不修改該物件的引用計數,這意味這弱指標它並不對物件的記憶體進行管理,在功能上類似於普通指標,然而一個比較大的區別是,弱指標能檢測到所管理的物件是否已經被釋放,從而避免訪問非法記憶體
template<typename T> class weak_ptr {
public:
template <typename Y>
weak_ptr(const shared_ptr<Y>& r);
weak_ptr(const weak_ptr& r);
~weak_ptr();
T* get() const;
bool expired() const;
shared_ptr<T> lock() const;
};
expired()用於檢測所管理的物件是否已經釋放;lock()用於獲取所管理的物件的強引用指標。