C++中智慧指標的簡單使用

YunShell發表於2014-03-30

     在C++中的類中,一定會有4大函式。建構函式,拷貝建構函式,賦值過載運算子,解構函式。如果在類的宣告中,我們沒有顯示的定義,那麼編譯器將會自動為我們完成。那麼各個函式的作用是什麼?為什麼編譯器會給我們合成呢?那就是說,在類的編譯過程中,或者說在物件的建立過程中,以上四個函式都必須存在。首先分析下他們各自的作用。

    建構函式(constructor):完全是為了構造物件而存在。對資料成員進行初始化。手段就是利用初始化成員列表或者在建構函式體內完成。本質 初始化的目的

   拷貝建構函式(copy constructor): 本質是為用已經存在的物件來構造待存在的物件。該物件此時還未存在。

   賦值過載運算子( copy assigment  operator):本質是對已經存在的物件進行重新整理。比如 a=b。a,b都存在,只是a重新整理為b.

   解構函式(destructor):在物件的銷燬時候,呼叫該函式。本質是為了回收記憶體

   那麼對於沒有顯示的使用拷貝構造和賦值過載運算子。進行的就是所謂的“淺拷貝”。即是完全的值拷貝。突出的不同就在於指標變數的問題。對於類中出現指標變數時候,進行淺拷貝的話,那麼兩個類的指標變數都只向同一塊記憶體,那麼在析構的時候,就會出現一塊記憶體析構兩次,出現記憶體洩露情況。

   如何能阻止這種情況呢?這就是拷貝建構函式的功能了。也就是說我們自己完全接管複製拷貝的過程,而不要編譯器為我們幹。

   智慧指標的使用。雖然使用上稍微複雜些,但是節省記憶體。

   智慧指標的思路:使用一個專門的類來管理記憶體。也就是說改類內部維護一個計數器,各個類中的指標都指向同一塊記憶體,但是隻有在計數器類內使用次數為0的情況下,才去銷燬記憶體。這樣就不會造成一塊記憶體被銷燬兩次了。

   下面見程式碼:

// 智慧指標的簡單使用
#include <iostream>
using namespace std;

class SmartPoint
{
private:
	SmartPoint(int *p):ptr(p),usecnt(1){}; //建構函式
	~SmartPoint(){delete ptr;};	//銷燬

	friend class Sample; //該智慧指標 用友元類來訪問
	size_t  usecnt;	//使用次數
	int *ptr;		//指向的指標
};

class Sample
{
public:
	Sample(int *p):smptr(new SmartPoint(p)){};				//建構函式
	Sample(const Sample &obj):smptr(obj.smptr){  ++smptr->usecnt;} //拷貝建構函式 維護指標
	~Sample()	//解構函式
	{
		if(--smptr->usecnt==0)
			delete smptr;
	}
	int getval(){return *(smptr->ptr);}
private:
	SmartPoint *smptr;
};

int main()
{ 
	int *p=new int(10);
	Sample *pa=new Sample(p);	//用p來建立a物件
	cout<<"a.smptr="<<pa->getval()<<endl;
	Sample *pb=new Sample((*pa));
	cout<<"b.smptr="<<pb->getval()<<endl;
	delete pa;
	delete pb;
	return 0;
}


     說明:上述程式碼中使用SmartPoint類來維護一個計數器usecnt和一個指標。當進行復制時候,該計數器加1,那麼當該計數器usecnt==0時候,則delete p;這個時候會自動去呼叫SmartPoint的解構函式,進行刪除記憶體。

   使用計數器的思想在windows OS很多見。

相關文章