不少人都誤覺得智能指針是一個指針,其實否則,智能指針不是指針,智能指針是一個模板,由智能指針實例化出來的的對象具備和常規指針類似的行爲,可是他可以自動的釋放所指向的對象,因此咱們稱之爲智能指針。若是咱們用普通指針來建立一個指向某個對象的指針,那麼咱們最後必需要手動釋放這塊空間,而智能指針它是一個類,它釋放空間是經過析構函數完成的,正是因爲有了這一層封裝機制,因此智能指針纔可以管理一個對象的生命週期。(定義一個類來封裝資源的分配和釋放,在構造函數完成資源的分配和初始化,在析構函數完成資源的清理,能夠保證資源的正確初始化和釋放。這樣的方法稱爲RAII)數組
起初在C++標準庫裏面是沒有智能指針的,直到C++11中才加入了shared_ptr和unique_ptr,weak_ptr。最先的智能指針在Boost庫裏面,Boost是爲C++標準庫提供擴展的一些C++程序的總稱,由Boost社區組織開發維護。ide
一、auto_ptr函數
auto_ptr在STL中早就存在了,auto_ptr是經過權限轉移的方式來防止值拷貝所帶來問題,所謂權限轉移就是說開闢的動態內存任什麼時候刻只能由一個指針指向。this
下面經過實現本身的AutoPtr來剖析一下auto_ptr。如今已經不用aotu_ptr了,經常使用的是scoped_ptr和shared_ptr.
spa
<span style="font-size:14px;">template<typename T> class AutoPtr //AutoPtr是一個類模板,不是指針類型 { public: AutoPtr(T* ptr=0); AutoPtr(AutoPtr<T>& ap); AutoPtr<T>& operator=(AutoPtr<T>& ap); T* Get(); T* Release(); void Reset(T* ptr=0); T& operator*(); T* operator->(); ~AutoPtr(); private: T* _ptr; }; template<typename T> T* AutoPtr<T>::Get() { return _ptr; } template<typename T> T* AutoPtr<T>::Release() { T* tmp = _ptr; _ptr = NULL; return tmp; } template<typename T> void AutoPtr<T>::Reset(T* ptr = 0) { delete _ptr; _ptr = ptr; ptr = NULL; } template<typename T> AutoPtr<T>::AutoPtr(T* ptr=0) :_ptr(ptr){} template<typename T> AutoPtr<T>::AutoPtr(AutoPtr<T>& ap) //auto_ptr採用權限轉移的方式,確保始終只有一個指針指向這塊空間 { _ptr = ap._ptr; ap._ptr = NULL; //權限轉移 } template<typename T> AutoPtr<T>& AutoPtr<T>::operator=(AutoPtr<T>& ap) { delete _ptr; _ptr = ap._ptr; ap._ptr = NULL; //權限轉移 return *this; } template<typename T> T& AutoPtr<T>::operator*() { return *_ptr; } template<typename T> T* AutoPtr<T>::operator->() //有特殊處理 { return _ptr; } template<typename T> AutoPtr<T>::~AutoPtr() { if (_ptr != NULL) { delete _ptr; _ptr = NULL; } }</span><span style="font-size: 19px;"> </span>
下面咱們先來介紹boost庫中的幾種經常使用的智能指針,因爲boost庫不是C++標準庫,因此咱們在使用boost中的智能指針以前先要下載一個boost庫,並把它包含到C++標準庫中。指針
一、scoped_ptr對象
因爲auto_ptr的行爲與真正的指針有很大區別,尤爲是權限轉移這種方法。爲了防止值拷貝帶來的問題,因此scoped_ptr從根本上就不容許拷貝和賦值(防賦值、防拷貝)。生命週期
template<typename T> class ScopedPtr //防拷貝,防賦值,使得scopedptr看起來更像一個指針類型,但實際上scopedptr是一個類模板 { public: explicit ScopedPtr(T* ptr); T& operator*(); T* operator->(); ~ScopedPtr(); T* Get() const; void Reset(T *p=0); void Swap(ScopedPtr<T>& sp); protected: ScopedPtr(const ScopedPtr<T>& sp); //將拷貝和賦值運算符聲明爲保護,防賦值、防拷貝 ScopedPtr<T>& operator=(const ScopedPtr<T>& ap); private: T* _ptr; }; template<typename T> T* ScopedPtr<T>::Get() const { return _ptr; } template<typename T> void ScopedPtr<T>::Reset(T *p = 0) { delete _ptr; _ptr = p; p = NULL; } template<typename T> void ScopedPtr<T>::Swap(ScopedPtr<T>& sp) { swap(_ptr,sp._ptr); } template<typename T> ScopedPtr<T>::ScopedPtr(T* ptr) :_ptr(ptr) {} template<typename T> T& ScopedPtr<T>::operator*() { return *_ptr; } template<typename T> T* ScopedPtr<T>::operator->() //有特殊處理 { return _ptr; } template<typename T> ScopedPtr<T>::~ScopedPtr() { if (NULL!= _ptr) { delete _ptr; _ptr =NULL; } }
二、scoped_array內存
scoped_array是用來管理數組的。ci
<span style="font-size:14px;">template<typename T> class ScopedArray { public: ScopedArray(T* ptr); ~ScopedArray(); T& operator[](size_t index); void Reset(T* ptr=0); T* Get() const; protected: ScopedArray(const ScopedArray<T>&); ScopedArray<T>& operator=(const ScopedArray<T>&); private: T* _ptr; }; template<typename T> void ScopedArray<T>::Reset(T* ptr = 0) { if (_ptr != ptr||_ptr==NULL) { delete[] _ptr; _ptr = ptr; ptr = NULL; } } template<typename T> T* ScopedArray<T>::Get() const { return _ptr; } template<typename T> ScopedArray<T>::ScopedArray(T* ptr) :_ptr(ptr) {} template<typename T> ScopedArray<T>::~ScopedArray() { if (NULL != _ptr) { delete[] _ptr; _ptr = NULL; } } template<typename T> T& ScopedArray<T>::operator[](size_t index) { return _ptr[index]; }</span><span style="font-size: 24px;"> </span>
三、shared_ptr
shared_ptr容許拷貝和賦值,其底層實現是以"引用計數"爲基礎的,經過引用計數來控制空間的釋放,當一塊空間建立時引用計數爲1,當有新的指針指向這塊空間時,引用計數加1,反之減1,直到引用計數減爲0時才真的釋放這塊空間。因此說shared_ptr更像一個指針。
template<typename T> class SharedPtr //採用引用計數,實現一個能夠有多個指針指向同一塊內存的類模板,SharedPtr是類模板,不是智能指針類型 { public: SharedPtr(T* ptr); SharedPtr(const SharedPtr<T>& sp); SharedPtr<T>& operator=(SharedPtr<T> sp); T& operator*(); T* operator->(); ~SharedPtr(); int Count() { return *_pCount; } private: void Release() { if (--(*_pCount) == 0) { delete _ptr; delete _pCount; _ptr = NULL; _pCount = NULL; } } private: T* _ptr; int* _pCount; //指向引用計數的空間 }; template<typename T> SharedPtr<T>::SharedPtr(T* ptr) :_ptr(ptr) , _pCount(new int(1)){} template<typename T> SharedPtr<T>::SharedPtr(const SharedPtr<T>& sp) { _ptr = sp._ptr; _pCount= sp._pCount; ++(*_pCount); } template<typename T> SharedPtr<T>& SharedPtr<T>::operator=(SharedPtr<T> sp) { std::swap(sp._ptr,_ptr); std::swap(sp._pCount,_pCount); return *this; } template<typename T> T& SharedPtr<T>::operator*() { return *_ptr; } template<typename T> T* SharedPtr<T>::operator->() { return _ptr; } template<typename T> SharedPtr<T>::~SharedPtr() { Release(); }
四、shared_array
shared_array也是管理數組的。
<span style="font-size:14px;">template<typename T> class SharedArray { public: SharedArray(T* ptr); ~SharedArray(); SharedArray(const SharedArray<T>& sp); SharedArray<T>& operator=(SharedArray<T> sp); T& operator[](size_t index); private: T* _ptr; int* _pCount; }; template<typename T> SharedArray<T>::SharedArray(T* ptr) :_ptr(ptr) , _pCount(new int(1)) {} template<typename T> SharedArray<T>::~SharedArray() { if (--(*_pCount) == 0) { delete[] _ptr; _ptr = NULL; delete _pCount; _pCount = NULL; } } template<typename T> SharedArray<T>::SharedArray(const SharedArray<T>& sp) { _ptr = sp._ptr; _pCount = sp._pCount; ++*pCount; } template<typename T> SharedArray<T>& SharedArray<T>::operator=(SharedArray<T> sp) { swap(_ptr,sp._ptr); swap(_pCount,sp._pCount); return *this; } template<typename T> T& SharedArray<T>::operator[](size_t index) { return _ptr[index]; }</span><span style="font-size: 24px;"> </span>