RAII(Resource Acquisition Is Initialization)
ide
資源分配即初始化,定義一個類來封裝資源的分配和釋放,在構造函數完成資源的分配和初始化,在析構函數完成資源的清理,能夠保證資源的正確初始化和釋放。函數
智能指針:用自動化或者說智能的指針來實現對動態內存的釋放。它是一個類,有相似指針的功能。ui
常見的智能指針:auto_ptr/scoped_ptr/scoped_array/shared_ptr/shared_array,因爲scoped_array和scoped_ptr比較相似,shared_array和shared_ptr又比較相似,因此咱們只實現auto_ptr/scoped_ptr/shared_ptr。this
1、auto_ptrspa
最開始auto_ptr的成員變量主要有T* _ptr,bool _owner,主要實現原理是在構造對象時賦予其管理空間的全部權,在析構函數中經過_owner的真否來釋放全部權,而且在拷貝或賦值後經過將_owner設爲false,轉移空間的全部權。具體實現代碼以下:指針
template <typename T> class AutoPtr { public: AutoPtr(T* ptr = NULL); AutoPtr(AutoPtr<T>& ap); AutoPtr<T>& operator=(AutoPtr<T>& ap); ~AutoPtr(); T& operator*()const; T* operator->()const; T* GetStr()const; protected: T* _ptr; bool _owner; }; template <typename T> AutoPtr<T>::AutoPtr(T* ptr) : _ptr(ptr), _owner(true) {} template <typename T> AutoPtr<T>::AutoPtr(AutoPtr<T>& ap) : _ptr(ap._ptr), _owner(true) { ap._owner = false; } template <typename T> AutoPtr<T>& AutoPtr<T>::operator=(AutoPtr<T>& ap) { if (this != &ap) { delete this->_ptr; this->_ptr = ap._ptr; this->_owner = true; ap._owner = false; } return *this; } template <typename T> AutoPtr<T>::~AutoPtr() { if (this->_ptr) { this->_owner = false; delete this->_ptr; } } template <typename T> T& AutoPtr<T>::operator*()const { return *(this->_ptr); } template <typename T> T* AutoPtr<T>::operator->()const { return this->_ptr; } template <typename T> T* AutoPtr<T>::GetStr()const { return (this->_ptr); }
主要問題:若是拷貝出來的對象比原來的對象出做用域,則原來的對象的_owner雖然爲false,但卻課訪問一塊已經釋放的一塊空間。對象
auto_ptr的第二種實現方法:仍是管理空間的全部權轉移,但這種實現方法中沒有_owner。構造和析構和上述實現方法相似,但拷貝和賦值後直接將_ptr賦爲空,禁止其在訪問原來的內存空間。具體代碼以下:內存
template <typename T> class AutoPtr { public: AutoPtr(); AutoPtr(T* ptr); AutoPtr(AutoPtr<T>& ap); AutoPtr<T>& operator=(AutoPtr<T>& ap); ~AutoPtr(); T& operator*()const; T* operator->()const; T* GetStr()const; protected: T* _ptr; }; template <typename T> AutoPtr<T>::AutoPtr() : _ptr(NULL) {} template <typename T> AutoPtr<T>::AutoPtr(T* ptr) : _ptr(ptr)//不能寫成const T* ptr,由於不然爲const類型的賦值給非const類型 {} template <typename T> AutoPtr<T>::AutoPtr(AutoPtr<T>& ap) : _ptr(ap._ptr) { ap._ptr = NULL; } template <typename T> AutoPtr<T>& AutoPtr<T>::operator=(AutoPtr<T>& ap) { if (this != &ap) { delete this->_ptr; this->_ptr = ap._ptr; ap._ptr = NULL; } return *this; } template <typename T> AutoPtr<T>::~AutoPtr() { if (this->_ptr) { delete this->_ptr; } } template <typename T> T& AutoPtr<T>::operator*()const { return *(this->_ptr); } template <typename T> T* AutoPtr<T>::operator->()const { return this->_ptr; } template <typename T> T* AutoPtr<T>::GetStr()const { return (this->_ptr); }
2、scoped_ptr資源
scoped_ptr的實現原理是防止對象的拷貝與賦值。具體實現是將拷貝構造函數和賦值運算符重載函數設置爲保護或私有,而且只聲明不實現,設置爲保護或私有是防止他人在類外本身實現。具體代碼以下:作用域
template <typename T> class ScopedPtr { public: ScopedPtr(T* ptr = NULL); ~ScopedPtr(); T* operator->()const; T& operator*()const; T* GetPtr()const; protected: ScopedPtr(const ScopedPtr<T>& ptr); ScopedPtr<T>& operator=(const ScopedPtr<T>& ptr); protected: T* _ptr; }; template <typename T> ScopedPtr<T>::ScopedPtr(T* ptr) :_ptr(ptr) {} template <typename T> ScopedPtr<T>::~ScopedPtr() { if (this->_ptr) { delete this->_ptr; } } template <typename T>//應用於類型爲結構體時 T* ScopedPtr<T>::operator->()const { return this->_ptr; } template <typename T> T& ScopedPtr<T>::operator*()const { return *(this->_ptr); } template <typename T> T* ScopedPtr<T>::GetPtr()const { return (this->_ptr); }
shared_ptr的實現及相關問題見下篇博客。