1. 程式人生 > >智慧指標--scoped_ptr shared_ptr weak_ptr

智慧指標--scoped_ptr shared_ptr weak_ptr

所謂智慧指標就是智慧/自動化的管理指標所指向的動態資源的釋放;

scopde_ptr--防拷貝

什麼叫做防拷貝?就是不允許一個地址空間的指標賦值給另一個指標,導致有兩個指標指向同一個地址;也就是說防拷貝能保證地址與指標是一一對應的關係;

實現方法:要拷貝,就需要通過物件來呼叫賦值運算子過載函式/拷貝建構函式,只要將這兩個成員函式私有化/保護化,就ok啦;

具體程式碼:

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;
};
shared_ptr--引用計數

允許多個指向同一塊地址;每增加一個指向該地址的指標計數器就加一;減少一個指向該地址的指標計數器減一,直到計數器的值為0的時候進行delete釋放這塊空間;

程式碼:

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;
};
但是share_ptr有一個迴圈引用的問題:


當在雙向連結串列時,想要釋放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()用於獲取所管理的物件的強引用指標。