1 // 参照カウンタによるスマートポインタを提供します。
3 // ここで定義されるスマートポインタは、scoped_ptrとは異なり、
4 // 最終的に参照しているデータが、解体責任を負う点で異なります。
5 // 最終的に参照しているデータを判定するため、参照カウンタ形式で
8 // また、このスマートポインタは配列を扱うことができます。
12 // smart_ptr<CHoge> h(new CHoge());
14 // smart_ptr<CHoge> ha();
17 #ifndef _UTAKATA_LIB_SMART_PTR_H_
18 #define _UTAKATA_LIB_SMART_PTR_H_
20 #include "lib/ref_delete.h"
24 template<class T> class smart_ptr {
26 template<class S> explicit
27 smart_ptr(S* p, bool owner = true, ref_delete_base* ref = NULL) :
28 obj_(NULL),ref_obj_(NULL) {
35 smart_ptr() : obj_(NULL),ref_obj_(NULL) {}
38 smart_ptr(const smart_ptr<T>& p) :
39 obj_(NULL),ref_obj_(NULL) {
44 // 自分にコピーされる前に、前のオブジェクトの参照カウントを
46 smart_ptr<T>& operator=(const smart_ptr<T>& obj) {
49 smart_ptr<T> tmp(obj);
55 virtual ~smart_ptr() {dec();}
58 virtual void release() {dec();}
60 //ここからは、ポインタの振りをするための仕掛け。
61 T& operator*() const {return *get();}
62 T* operator->() const {return get();}
65 bool operator==(const smart_ptr<T>& rh) const {
66 return obj_ == rh.obj_;
69 bool operator!=(const smart_ptr<T>& rh) const {
70 return !(*this.obj_ == rh.obj_);
73 // 現在保持しているポインタを明示的に返します。
75 if (ref_obj_ == NULL) {
82 // 内部で参照しているオブジェクトがNULLであるかどうかを返します。
83 bool is_null() const {
84 return ref_obj_ == NULL && obj_ == NULL;
87 // オブジェクトが単一の場所からのみ参照されているか。
88 bool is_only_ref() const {
89 return ref_obj_->reference() == 1;
92 //=============================================
94 //=============================================
96 // 渡されたsmart_ptrが格納しているオブジェクトを参照するようにします。
97 // テンプレートパラメータSは、Tの派生クラスである必要があります。
99 void upcast(const smart_ptr<S>& p) {
100 if (reinterpret_cast<void*>(this) != reinterpret_cast<void*>(&p)) {
104 ref_obj_ = p.ref_obj();
106 if (ref_obj_ != NULL) {
112 // 現在保持している型を新規に生成します。新規の生成では、デフォルトコ
119 // 外部より明示的に新しい管理対象オブジェクトを渡して初期化を行います。
120 // ownerが指定されない場合、デフォルトで管理が行われます。
122 void reset(S* object, bool owner = true) {
124 if (object != NULL) {
129 // 外部より明示的に新しい管理対象オブジェクトを渡して初期化を行います。
130 // ownerが指定されない場合、デフォルトで管理が行われます。
131 // 削除時には、渡されたdeleterによって処理が行われます。
133 void reset(S* _p, ref_delete_base* ref, bool owner = true) {
135 if (_p != NULL && ref != NULL) {
136 init(_p, owner, ref);
142 // smart_ptrの初期化処理を行います。ref_delete_baseが指定されている場合
143 // には、渡されたオブジェクトが解体オブジェクトとして利用されます。
145 void init(S* _p, bool owner, ref_delete_base* ref = NULL) {
148 if (ref_obj_ != NULL) {
155 ref_obj_ = new ref_noarray_object<S>(_p);
157 ref_obj_ = new ref_null_object<S>(_p);
160 ref_obj_->set_reference(1);
161 ref_obj_->set_maxnum(1);
162 ref_obj_->set_objsize(sizeof(S));
163 ref_obj_->set_owner(owner);
166 // 渡されたsmart_ptrを参照するように変更し、参照数を加算します。
167 void inc(const smart_ptr<T>& p) {
168 ref_obj_ = p.ref_obj_;
170 if (ref_obj_ != NULL) {
175 void swap(smart_ptr<T>& p) {
176 std::swap(ref_obj_, p.ref_obj_);
177 std::swap(obj_, p.obj_);
180 // 現在自身が参照しているオブジェクトの参照数を減算し、
182 // 参照数の減算時、参照数がゼロになった場合にのみ、ref_objをdeleteします。
184 if (ref_obj_ != NULL) {
185 if (ref_obj_->dec_ref()) {
193 //========================================
195 //========================================
197 // 現在保持しているデリータを返します。
198 ref_delete_base* ref_obj() const {return ref_obj_;}
200 // 現在保持しているオブジェクトを返します
201 T* obj() const {return obj_;}
205 T* obj_; //保持すべきオブジェクト。参照カウントオブジェクトと同一
207 ref_delete_base* ref_obj_; //参照カウントオブジェクト
209 }; // end of namespace utility
211 #endif /* _UTAKATA_LIB_SMART_PTR_H_ */