C++:智能指針( scope_ptr)

新智能指針的加入:

C++11之前,智能指針只有 auto_ptr 一種,但是後來發現它並不能很好的保證指針的安全可靠性,隨之又出現了

shared_ptr     unique_ptr     weak_ptr   scope_ptr 這幾種智能指針。

假如存在這樣的代碼
int main()
{
    SmartPtr<int> sp1(new int);
    SmartPtr<int> sp2(sp1);

    *sp1 = 20;
     return 0;
}

這裏,SmartPtr即爲之前博客實現的auto_ptr,顯而易見,*sp1=20;這行會出現崩潰。

               

解決方案:

 之前的auto_ptr,管理權唯一,釋放權也唯一,現在要使智能指針管理權不唯一,釋放權唯一。

帶有標誌位(flag)的智能指針

如圖:

                 

             

代碼:

#include<iostream>

using namespace std;

template<typename T>
class SmartPtr
{
public:
	SmartPtr(T* ptr) :mptr(ptr)
	{
		flag = true;
	}
	SmartPtr(const SmartPtr<T>& rhs):mptr(rhs.mptr)
	{
		flag = rhs.flag;
		rhs.flag = false;
	}
	SmartPtr<T>& operator=(const SmartPtr<T>& rhs)
	{
		if (this != &rhs)
		{
			~SmartPtr();
			mptr = rhs.mptr;
			flag = rhs.flag;
			rhs.flag = false;
		}
		return *this;
	}
	~SmartPtr()
	{
		if (flag)
		{
			delete mptr;
		}
		mptr = NULL;
	}
	T& operator*()
	{
		return *mptr;
	}
	T* operator->()
	{
		return mptr;
	}
private:
	T* mptr;
	mutable bool flag;//去除常性
};

int main()
{
	SmartPtr<int> sp1(new int);
	SmartPtr<int> sp2(sp1);
        SmartPtr<int> sp3(sp1);

	*sp1 = 20;

	return 0;
}

這裏程序不會崩潰,有釋放權的只有sp2。

又一個問題

因爲釋放權的轉移,有可能導致堆內存被提前釋放

void func(SmartPtr<int> sp)//實參傳形參 調用拷貝構造
{

}

int main()
{
	SmartPtr<int> sp1(new int);
	SmartPtr<int> sp2(sp1);
	SmartPtr<int> sp3(sp1);

	func(sp2);//;執行結束後,形參對象銷燬  相當於堆內存已經歸還給系統
	*sp1 = 20;//使用不可使用的內存塊 野指針 該內存塊可能被再分配
	return 0;
}

調用這個函數,實參傳形參 調用拷貝構造,func(sp2);//;執行結束後,形參對象銷燬  相當於堆內存已經歸還給系統。

*sp1 = 20;//使用不可使用的內存塊 野指針 該內存塊可能被再分配,會出現不可預期的數據錯誤。

解決: ScopePtr  不允許多個智能指針對象指向同一塊堆內存

#include<iostream>

using namespace std;

template<typename T>
class ScopePtr//不允許多個智能指針對象指向同一塊堆內存
{
public:
	ScopePtr(T* ptr=NULL):mptr(ptr)
	{
		//mptr = ptr;
	}
	~ScopePtr()
    {
		delete mptr;
		mptr = NULL;
	}
	T& operator*()
	{
		return *mptr;
	}
	T* operator->()
	{
		return mptr;
	}
private:
	ScopePtr(const ScopePtr<T>& rhs);//不需要調用,因爲不允許多個智能指針對象指向同一塊堆內存
	ScopePtr<T>& operator=(const ScopePtr<T>& rhs);//不允許多個智能指針對象指向同一塊堆內存
private:
	T* mptr;
};

int main()
{
	int* p = new int;
	ScopePtr<int> sp1(p);
	ScopePtr<int> sp2(p);
	ScopePtr<int> sp3(p);//後構造的先析構
	return 0;
}

    int* p = new int;
    ScopePtr<int> sp1(p);
    ScopePtr<int> sp2(p);
    ScopePtr<int> sp3(p);//後構造的先析構
    

這個程序會崩潰,後構造的先析構,然後先構造的再析構時,delete野指針,程序崩潰。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章