C++ 之 智慧指標實現
阿新 • • 發佈:2019-02-15
面試的時候,被問到了智慧指標,之前的確看過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~~