什麼是智能指針?
智能指針實質上是一個類,定義一個類來封裝資源的分配和釋放。這個類的構造函數中傳入一個指針,完成資源的分配和初始化。在析構函數中釋放傳入的該指針,完成資源的釋放。
爲什麼要用智能指針?
智能指針就是智能,自動化的管理指針所指向的動態資源。
例如以下情況:代碼中經常會忘記釋放動態開闢的內存資源,導致內存泄露。
// case1 void Test2() { int* p1 = new int(2); bool isEnd = true; //... if (isEnd) { delete p1; return; } //... delete p1; } // case2 void DoSomeThing() { //... throw 2; //... } void Test2() { int* p1 = new int(2); //... try { DoSomeThing(); } catch (...) { delete p1; throw; } //... delete p1; }
智能指針的簡單實現。
Auto_ptr:不能共享所有權,只要出現兩個指針指向同一塊資源,就釋放前一個指針的管理權。保證只有一個指針指向一塊資源。
Scoped_ptr:將類中的成員函數拷貝構造和賦值運算符只申明爲protected,不定義。所以不可能有兩個指針指向同一個對象。
Shared_ptr:採用引用計數的方法。將一個計數器與類指向的對象相關聯,引用計數跟蹤共有多少個類對象共享同一指針。
ScopedArray和Scoped_ptr類似,只是操作的是數組。SharedArray同理。
template <class T> class AutoPtr { public: AutoPtr(T*ptr) :_ptr(ptr) {} AutoPtr( AutoPtr<T>&ap) :_ptr(ap._ptr) { ap._ptr = NULL; } AutoPtr<T>&operator=(const AutoPtr<T>&ap) { if (this != &ap) { delete _ptr; _ptr = ap._ptr; ap._ptr = NULL; } } ~AutoPtr() { if (_ptr) { delete _ptr; _ptr = NULL; } } T&operator*() { return *_ptr; } T*operator->() { return _ptr; } T*GetPtr() { return _ptr; } protected: T*_ptr; }; struct Node { int _data; Node*_next; }; void Test_AutoPtr() { int*p1 = new int(2); int*p2 = p1; int*p3 = p2; *p3 = 10; delete p1; AutoPtr<int>ap1(new int(2)); AutoPtr<int>ap2=ap1; //此時ap1爲NULL,無管理權 AutoPtr<int>ap3(ap2); //此時ap2爲NULL,無管理權 //*ap2 = 10; //程序崩潰 *ap3 = 10; AutoPtr<Node>sp1(new Node); sp1->_data = 10; } template<class T> class ScopedPtr { public: ScopedPtr(T*ptr) :_ptr(ptr) {} ~ScopedPtr() { if (_ptr) { delete _ptr; _ptr = NULL; } } T&operator*() { return *_ptr; } T*operator->() { return _ptr; } T*GetPtr() { return _ptr; } protected: //只申明,不定義,防止拷貝構造和賦值運算符重載。 ScopedPtr(const ScopedPtr<T>&sp); //保護,防止在外定義。若寫爲public,則有可能在類外定義。 ScopedPtr<T>& operator=(const ScopedPtr<T>&sp); protected: T*_ptr; }; void Test_ScopedPtr() { ScopedPtr<int>sp1(new int(3)); //ScopedPtr<int>sp2(sp1); //protectd:無法訪問 } template <class T> class ScopedArray { public: ScopedArray(T*ptr) :_ptr(ptr) {} ~ScopedArray() { if (_ptr) { delete[]_ptr; } } T&operator[](size_t Index) { return _ptr[Index]; } T&operator*() { return *_ptr; } T*operator->() { return _ptr; } T*GetPtr() { return _ptr; } protected: ScopedArray(const ScopedArray<T>&sp); ScopedArray<T>&operator=(const ScopedArray<T>&sp); protected: T*_ptr; }; void Test_ScopedArray() { ScopedArray<int>sp1(new int[5]); //ScopedPtr<int>sp2(sp1); } template <class T> class SharedPtr { public: SharedPtr(T*ptr) :_ptr(ptr) , _Pcount(new long(1)) {} SharedPtr(const SharedPtr<T>&sp) :_ptr(sp._ptr) , _Pcount(sp._Pcount) { ++*(_Pcount); } //SharedPtr<T>&operator=(const SharedPtr<T>&sp) //傳統寫法 //{ // if (this != &sp) // { // if (--(*_Pcount) == 0) // { // delete _ptr; // delete _Pcount; // } // _ptr = sp._ptr; // _Pcount = sp._Pcount; // ++(*_Pcount); // } // return *this; //} SharedPtr<T>&operator=(const SharedPtr<T>sp) //現代寫法 { swap(_ptr, sp._ptr); swap(_Pcount, sp._Pcount); return *this; } ~SharedPtr() { if (--(*_Pcount) == 0) { delete _ptr; delete _Pcount; } } T&operator*() { return *_ptr; } T*operator->() { return _ptr; } T*GetPtr() { return _ptr; } long GetCount() { return *_Pcount; } protected: T*_ptr; long*_Pcount; }; void Test_SharedPtr() { SharedPtr<int>sp1(new int(2)); SharedPtr<int>sp2(sp1); } template <class T> class SharedArray { public: SharedArray(T*ptr) :_ptr(ptr) , _Pcount(new long (1)) {} SharedArray(const SharedArray<T>&sp) :_ptr(sp._ptr) , _Pcount(sp._Pcount) { ++*(_Pcount); } SharedArray<T>&operator=(const SharedArray<T>sp) //現代寫法 { swap(_ptr, sp._ptr); swap(_Pcount, sp._Pcount); return *this; } ~SharedArray() { if (--(*_Pcount) == 0) { delete[] _ptr; delete _Pcount; } } T&operator*() { return *_ptr; } T*operator->() { return _ptr; } T*GetPtr() { return _ptr; } T&operator[](size_t Index) { return _ptr[Index]; } long GetCount() { return *_Pcount; } protected: T*_ptr; long*_Pcount; }; void Test_SharedArray() { SharedArray<int>sp1(new int[5]); SharedArray<int>sp2(sp1); }