C++:智能指針(auto_ptr)

智能指針:
       在C++中使用堆內存是非常頻繁的操作,堆內存的申請和釋放都由程序員自己管理。使用普通指針,容易造成堆內存泄露,二次釋放等問題,使用智能指針能更好的管理堆內存。C++11中引入了智能指針的概念,方便管理堆內存。

棧、堆區別

棧:系統開闢 系統釋放

堆:手動開闢 手動釋放

設計:手動開闢 系統釋放

圖示:

                        

手動開闢堆內存,利用對象生存週期結束後會調用析構,讓對象來管理這個堆內存,從而達到 手動開闢,系統析構的目的。

最初始的智能指針:管理權唯一
如果有多個智能指針指向同一個堆內存,會在拷貝構造或賦值過程中讓其他的智能指針失效(置空)

#include<iostream>

using namespace std;

template<typename T>
class SmartPtr
{
public:
	SmartPtr(T* ptr=NULL):mptr(ptr){}
	SmartPtr(const SmartPtr& rhs):mptr(rhs.mptr)//讓兩個智能指針指向同一個堆內存
	{
		rhs.Release();
	}
	SmartPtr<T> operator=(const SmartPtr<T>& rhs)
	{
		if (this != &rhs)
		{
			delete mptr;//要麼有唯一智能指針指向堆內存,要麼指向空 
			mptr = rhs.mptr;
			rhs.Release();
		}
		return *this;
        }
	~SmartPtr()
	{
		delete mptr;
		mptr = NULL;
	}
private:
	void Release()const//舊的智能指針置爲空
	{
		(T*)mptr = NULL;
	}
private:
	T* mptr;
};

int main()
{
	int *p=new int;//堆內存
	SmartPtr<int> sp1(p);
	SmartPtr<int> sp2(sp1);
        sp1=sp2;
	return 0;
}

調試結果:

        

可以看出,當生成sp2時,sp1指向爲空,指向的內存正是p所指向的堆內存。
        

可以看出,sp1=sp2;執行後,內存的管理權在sp1手上。

普通指針有指向和解引用的使用方法,同理智能指針也具有,需要運算符的重載。

#include<iostream>

using namespace std;

template<typename T>
class SmartPtr
{
public:
	SmartPtr(T* ptr = NULL) :mptr(ptr) {}
	SmartPtr(const SmartPtr& rhs) :mptr(rhs.mptr)//讓兩個智能指針指向同一個堆內存
	{
		rhs.Release();
	}
	SmartPtr<T>& operator=(const SmartPtr<T>& rhs)
	{
		if (this != &rhs)
		{
			delete mptr;//要麼有唯一智能指針指向堆內存,要麼指向空 
			mptr = rhs.mptr;
			rhs.Release();
		}
		return *this;
    }
	T& operator*()//解引用運算符的重載
	{
		return *mptr;
	}
	T* operator->()//指向運算符的重載
	{
		return mptr;
	}
	~SmartPtr()
	{
		delete mptr;
		mptr = NULL;
	}
private:
	void Release()const//舊的智能指針置爲空
	{
		(T*)mptr = NULL;
	}
private:
	T* mptr;
};

class Test
{
public:
	Test(int a):ma(a){}
	void Show()
	{
		cout << ma << endl;
	}
private:
	int ma;
};

int main()
{
	int *p=new int;//堆內存
	SmartPtr<int> sp1(p);
	SmartPtr<int> sp2(sp1);
	sp1 = sp2;
        //普通指針的用法
	Test *ptest = new Test(30);//成員變量是 Test *mptr;
	ptest->Show();
	//智能指針的用法
	SmartPtr<Test> sp3(ptest);
	sp3->Show();
	(*sp3.operator->()).Show();
	return 0;
}

解釋:(*sp3.operator->()).Show();//(sp3.operator->())->Show();

sp3.operator->()返回一個 T* 指針,*T解引用,即對象,對象調用方法,合情合理。

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