スマートポインタ(機能限定版)
スマートポインタとしての最低限の機能だけを実装してみますた。
template<class T> class SmartPtr { public: SmartPtr() : _object(NULL), _counter(NULL) { } // コピーコンストラクタ SmartPtr(const SmartPtr& s) : _object(NULL), _counter(NULL) { Set(s); } // ポインタのセット explicit SmartPtr(T* p) : _object(p), _counter(new int(1)) { } // 代入演算子 SmartPtr& operator=(const SmartPtr& s) { Set(s); return (*this); } // デストラクタ ~SmartPtr() { Release(); } // スマートポインタのセット void Set(const SmartPtr& s) { if ((void*)this != (void*)&s) { // 解放して、新しいスマートポインタをセットし直す Release(); _object = s._object; _counter = s._counter; // コピーされたので参照数を増やす if (_counter != NULL) { ++*_counter; } } } // スマートポインタの解放 void Release() { // 解放されたので参照数を減らす if (_counter != NULL && --*_counter == 0) { delete _object; delete _counter; } _object = NULL; _counter = NULL; } // ポインタの取得 T* GetPointer() const { return _object; } // アロー演算子 T* operator->() const { return GetPointer(); } // 間接参照演算子 T& operator*() const { return *GetPointer(); } private: T* _object; int* _counter; };
出来ること:
- 参照カウントによる自動解放
- ポインタのセット
- SmartPtr<T> 同士のコピー
- operato->, operator* での間接参照
出来ないこと:
- new で生成したポインタ以外の解放
- SmartPtr<T> と SmartPtr<U> でのコピー
- 途中でポインタをセットし直す
- null の代入
- null との比較
- SmartPtr 同士の比較
こうしてみれば、スマートポインタってめちゃめちゃ単純なクラスだってのが分かりますね。。
↓おまけ
template<class T> class Array { public: Array() : _object(NULL), _counter(NULL), _length(0) { } // コピーコンストラクタ Array(const Array& s) : _object(NULL), _counter(NULL), _length(0) { Set(s); } // ポインタと長さのセット explicit Array(T* p, int length) : _object(p), _counter(new int(1)), _length(length) { } // 内部で length 個の配列を作る explicit Array(int length) : _object(new T[length]), _counter(new int(1)), _length(length) { } // 代入演算子 Array& operator=(const Array& s) { Set(s); return (*this); } // デストラクタ ~Array() { Release(); } // スマート配列のセット void Set(const Array& s) { if ((void*)this != (void*)&s) { Release(); _object = s._object; _counter = s._counter; if (_counter != NULL) { ++*_counter; } } } // スマート配列の解放 void Release() { // 解放されたので参照数を減らす if (_counter != NULL && --*_counter == 0) { delete[] _object; delete _counter; } _object = NULL; _length = 0; _counter = NULL; } // ポインタの取得 T* GetPointer() const { return _object; } // インデクサ T& operator[](int index) const { _ASSERT(0 <= index && index < _length); return _object[index]; } // 長さの取得 int GetLength() const { return _length; } private: T* _object; int _length; int* _counter; };