1. 程式人生 > >C++ 之 智慧指標實現

C++ 之 智慧指標實現

面試的時候,被問到了智慧指標,之前的確看過C++ primer,然而,都忘掉了。。哭。。自己實現了一下share_ptr。。寫完以後翻了翻書,才發現,和書上的並不差多少。。尷尬

智慧指標型別: share_ptr, weak_ptr, unique_ptr

template <typename T> class smartPtr
{
public:
	smartPtr() :ptr(new T(0)), ptrCount(new int(1))		// 任何構造方式都能呼叫*p,不會出錯,如果初始化為nullptr,呼叫*p會出錯
	{
		cout <<"empty smart pointer construct ing ~~" <<endl;
	}
	smartPtr(const T t) :ptr(new T(t)), ptrCount(new int(1)) 
	{
		cout<<"smart pointer construct ing ~~"<<endl;
	}
	smartPtr(smartPtr &rhs) : ptr(rhs.ptr), ptrCount(&(++(*rhs.ptrCount)))  //拷貝構造
	{
		cout<<"smart pointer copy construct ing~~"<<endl;
	}
	T& operator*() 
	{
		//cout << "operator * is called" << endl;
		return *ptr;		
	}
	T* operator->() 
	{
		//cout << "operator -> is called" << endl;
		return &(operator *());  // c++ primer 504p, 委託給解引用運算子
	}
	int getCount() 
	{
		return *( ptrCount);
	}
	smartPtr& operator=(smartPtr &rhs)   //賦值運算子
	{
		//cout << "operator = is called" << endl;
		(*( ptrCount))--;
		(*(rhs.ptrCount))++;
		if ((*ptrCount) == 0)
		{
			delete  ptr;
			delete  ptrCount;
			ptr = nullptr;
			ptrCount = nullptr;
		}  
		 ptr = rhs.ptr;
		 ptrCount = rhs.ptrCount;
		return *this;
	}
	~smartPtr()
	{
		cout << "destructor is called, count is "<<*( ptrCount) << endl;
		if (--*ptrCount == 0)
		{
			delete ptr;
			ptr = nullptr;
		}
	}
private:
	int *ptrCount;
	T * ptr;
};

用到的知識點

1. 模板,模板可以擴大傳入引數的類型範圍 比如,基本型別,int, double, string..這些應該都沒什麼問題,其他更復雜的類型別,可能需要定義一下 << 運算子

2. 運算子過載,根據share_ptr的特性,要有一個計數器,這樣就必須過載 = (賦值運算子)。還有 * (解引用) 和 -->(成員訪問)。 計數器的其他實現方法,可以參考(http://blog.csdn.net/hackbuteer1/article/details/7561235)

3. 建構函式,拷貝建構函式

4. 計數器,用指標型別,方便共享

測試例子:

int main(int argc,char *argv[])
{
	smartPtr<int> p(42);
	smartPtr<int> q;
	smartPtr<int> r(p);		//copy initialize
	cout << "p = " << *p << "; q = " << *q << endl;
	cout << "p count " << p.getCount() << "; q count " << q.getCount() << endl;
	q = p;
	cout << "after q=p q is " << *q << endl;
	cout << "p count " << p.getCount() << "; q count " << q.getCount() << endl;
}
結果:

正常測試效果看起來還可以,不知道有沒有和我一樣暴力的程式設計師,會寫:

smartPtr<int> p=*(new smartPtr<int>(40));

這樣的程式碼。 由於在new裡面呼叫了一次建構函式,使得count多出了1,而無法正確釋放。( new運算子 1. 返回一片raw空間  2. 呼叫建構函式 3. 返回指標 )

執行效果,如下: 

如果有解決這個問題的方法,還望不吝賜教~~

菜鳥一枚,如果有錯誤,請留下您的高見~~Thanks~~ 大笑