1 #ifndef ___HGL___smart_ptr___
2 #define ___HGL___smart_ptr___
4 #include "ref_delete.h"
11 class smart_ptr_base {
13 virtual ~smart_ptr_base(){}
19 smart_ptr<CHoge> h(new CHoge);
20 とやれば、後はコピーしても解体責任を委譲したりして、
21 ちゃんとdeleteしてくれるようなクラス。
22 また、配列もとれるようにして、配列であっても
23 通常のポインタであっても、ちゃんとdeleteとdelete[]を
31 もしくは、CHogeの派生クラスSHogeを生成したりする場合は、
32 h.addArray(new SHoge[10],true,10);
37 class smart_ptr // : public smart_ptr_base
42 //このコンストラクタでは、配列の生成は出来ないことになっている。
43 template<class S> explicit
44 smart_ptr(S* p, bool owner = true, ref_delete_base* ref = NULL) :
45 obj_(NULL),ref_obj_(NULL),index_(0) {
52 smart_ptr() : obj_(NULL),ref_obj_(NULL),index_(0) {
56 smart_ptr(const smart_ptr<T>& p) :
57 obj_(NULL),ref_obj_(NULL),index_(0) {
63 virtual ~smart_ptr() {dec();}
66 virtual void release() {dec();}
68 //ここからは、ポインタの振りをするための仕掛け。
69 T& operator*() const {return *get();}
70 T* operator->() const {return get();}
73 smart_ptr<T>& operator++() {incIndex();return *this;}
74 smart_ptr<T>& operator++(int n) {incIndex();return *this;}
75 smart_ptr<T>& operator--() {decIndex();return *this;}
76 smart_ptr<T>& operator--(int n) {decIndex();return *this;}
79 T& operator[](int n) const {return *get(n + 1);}
81 smart_ptr<T>& operator=(const smart_ptr<T>& obj) {
83 //前のオブジェクトの参照カウントを減らした後、
94 保持するメモリから、指定された場所のメモリを取得する。
97 @return 指定された位置のテンプレートで指定されたオブジェクト
99 T* get(int n = 1) const {
100 //配列、単一変数どちらにでも対応するため、
104 if (ref_obj_ == NULL) {
108 if (index_ + n > ref_obj_->getMaxNum() || index_ + n < 0) {
113 //オブジェクトの先頭アドレス+オブジェクトのサイズ*(インデックス+引数)
114 //なお、この際に、index_ = 0かつ、n = 1である場合、
115 //先頭アドレス+オブジェクトサイズということになり、どう考えてもアクセス違反になる。
116 return (T*)((unsigned char*)obj_ + (ref_obj_->getObjSize() * (index_ + n - 1)));
119 //==============================================
120 //疑似イテレーターとして使用するための関数群
121 //==============================================
125 インデックスが、限界に達していないかどうか
126 ここで言う限界とは、MaxNumで、つまり添え字+1をさす。
128 @return bool 達している場合はtrue
131 if (ref_obj_ != NULL) {
132 return ref_obj_->getMaxNum()-1 < index_?true:false;
142 @return bool 先頭である場合はtrue
145 return index_ == 0?true:false;
153 bool isNull() const {
154 return ref_obj_==NULL&&obj_==NULL?true:false;
164 if (ref_obj_ != NULL) {
165 index_ = ref_obj_->getMaxNum()-1;
181 //=============================================
183 //=============================================
186 * @brief アップキャストを行う。SはTの派生クラスであること。
187 * また、その特性上同一性チェックが困難であるので、こればかりは仕方がない。
188 * @param const smart_ptr<S>& スマートポインタ
189 * @return smart_ptr<T>& アップキャスト後の自身。
192 smart_ptr<T>& upcast(const smart_ptr<S>& p) {
194 if (reinterpret_cast<void*>(this) !=
195 reinterpret_cast<void*>(const_cast<smart_ptr<S>*>(&p)) ) {
196 //pがさすオブジェクトをこのオブジェクトもさすことになるので、
202 ref_obj_ = p.getRefObj();
203 index_ = p.getIndex();
205 if (ref_obj_ != NULL) {
214 * @brief 指定した型の追加生成構文
215 * コンストラクタで何も指定しない場合、これを実行することで、再生成を行う。
219 init(new T, true, 1);
225 関数テンプレートを使ってはいるが、必ずTとおなじ、
227 @param S* p 対象とするオブジェクト
228 @param bool owner 所有権の有無
233 void add(S* _p, bool owner = true) {
241 * @brief デリータを指定した追加生成構文。
245 void add(S* _p, bool owner, ref_delete_base* ref) {
247 if (_p != NULL && ref != NULL) {
248 init(_p, owner, 1, ref);
255 現在のオブジェクトの型を、指定個数作成する場合。
256 @param bool owner 所有権の有無
261 void addArray(bool owner, int n) {
264 init(new T[n], owner, n);
266 init(new T, owner, 1);
273 こちらは、配列オブジェクトを生成する際に使用される関数。
274 @param S p 対象とするオブジェクト
275 @param bool owner 所有権の有無
281 void addArray(S _p, bool owner, int n) {
284 init(new S[n], owner, n);
292 @return int 現在のインデックス
294 int getIndex() const {return index_;}
300 @return ref_delete_base* 削除オブジェクトのポインタ
302 ref_delete_base* getRefObj() const {return ref_obj_;}
308 @return T* オブジェクトのポインタ
310 T* getObj() const {return obj_;}
318 参照カウント、オブジェクトの個数を設定する。
319 @param template _p 保持するべきオブジェクト
320 @param bool owner 所有権の湯有無
321 @param int n オブジェクトの個数
322 @param ref_delete_base* ref デフォルトはNULL。外部からのコピーならば非NULL
327 void init(S* _p, bool owner, int n, ref_delete_base* ref = NULL) {
332 if (ref_obj_ != NULL) {
333 //このとき、すでにdec_refとかはやってあることが前提。
342 ref_obj_ = new ref_noarray_object<S>(_p);
344 ref_obj_ = new ref_array_object<S>(_p);
348 ref_obj_ = new ref_null_object<S>(_p);
353 ref_obj_->setMaxNum(n);
354 ref_obj_->setObjSize(sizeof(S));
355 ref_obj_->setOwner(owner);
361 渡されたsmart_ptrの参照数を一つ増やす。
362 @param const smart_ptr<T>& p 参照カウントを増やすオブジェクト
366 void inc(const smart_ptr<T>& p) {
367 index_ = p.getIndex();
368 ref_obj_ = p.getRefObj();
371 if (ref_obj_ != NULL) {
379 実行されたら、ref_obj_およびobj_は
385 //dec_refは、オブジェクトを削除したかどうかを返す。
386 //削除されている場合は、参照オブジェクトを削除しなければならない。
387 if (ref_obj_ != NULL) {
388 if (ref_obj_->dec_ref()) {
402 void incIndex() {index_++;}
410 void decIndex() {index_--;}
412 //========================================
414 //========================================
418 T* obj_; //保持すべきオブジェクト。参照カウントオブジェクトと同一
420 ref_delete_base* ref_obj_; //参照カウントオブジェクト
422 int index_; //現在のインデックス