C++智能指針由來與實現思想以及實現一個簡單的指針指針

智能指針的由來和基本思想

裸指針int *p = new int; ,其實就是C風格的指針。

裸指針的缺點:
1.必須手動釋放資源,手動調用delete;
2.由於程序邏輯的錯誤return或者throw異常,導致釋放資源的代碼delete ptr沒有被調用到;
3.程序運行過程中,發生異常,導致釋放資源的代碼沒有被調用到。

智能指針 : 智能(不管程序運行發生什麼意外的情況,一定會幫用戶把資源釋放掉),不過利用的思想正是對象出作用域,編譯器會自動調用對象的析構函數,保證引用的堆空間被正確的釋放。

  • 數據段:在程序運行結束後,數據段的數據纔會被釋放;
  • 堆: 需要手動調用釋放函數釋放資源(堆嚴格意義上也屬於數據,上面的數據主要指全局和static對象);
  • 棧:** 函數調用結束會自己釋放(智能指針基於該思想設計),退出局部作用域,編譯器會自動添加銷燬局部變量的指令。**
  • 自定義局部作用域:
int main(){
	int a = 10;
	{
	std::vector<int> vec;
	} //這也是一個局部的作用域,出右括號vec將不存在
}

實現一個智能指針:底層是我們經常使用的裸指針,通過構造函數構造一個棧上的對象,在局部對象出作用域前會自動調用對象的析構函數,即就是釋放底層裸指針所引用的外部資源。C++11標準委員會將智能指針從Boost庫中引用過來。

實現一個不帶引用計數的智能指針:

template <typename T>
class CSmartPtr{
public:
CSmartPtr(T *ptr = NULL)
		:mptr(ptr){}
~CSmartPtr(){
	delete mptr;
}

T& operator*(){
	return *mptr;
}
const T& operator*()const{
	return *mptr;
}
T* operator->(){
	return mptr;
}

T* operator->()const{
	return mptr;
}
private:
	T *mptr;
};

class A
{
public:
	void func(){ cout << "call A::func" << endl; }
};

//對智能指針的操作最終轉成對底層普通指針的操作,當然包括對運算符重載函數的
int main(int argc, char* argv[]){
	CSmartPtr <int> ptr1(new int);
	*ptr1 = 30;//表面看起來是在解引用智能指針,實際上調用operator*,解引用封裝的裸指針
	cout << *ptr1 << endl;

	CSmartPtr <A> ptr3(new A());
	(*ptr3).func();
	ptr3->func();//operator->返回的是封裝的裸指針,然後裸指針再去調用func

	//智能指針對象調用->運算符重載函數返回一個普通指針,普通指針調用對應的方法
	const CSmartPtr <A> ptr4(new A());
	//(*ptr4).func();
	ptr4->func();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章