如何实现引用计数型指针类?
这是一段引用计数指针的代码,目标是一个轻量级的、高效率的实现,避免通常实现中的频繁的new/delete引用计数的存储空间。
一些说明:
Q:为什么在ref_count的release中delete对象,而不是让外部的ref_count_ptr来释放对象?
A:将对象的销毁放到比较高的层次上,从而使得程序员更容易控制对象的销毁策略,看上去是非常有诱惑力的。但是,问题在于,我们使用ref_count_ptr时,意味着我们需要将这个对象传来传去。这个过程可能跨越不同的module.不同module之间的存储管理可能是完全不同的,如果混用,将导致不可预料的行为.
Q:ref_count_ptr为什么没有提供协变?
A:考虑到assembler的特性,父类和子类被组装之后,assembler<>的裸指针也已经失去了相互转换的能力,因此,在这里提供协变没什么意义。
#ifndef REFCOUNT_H #define REFCOUNT_H #include "contract.h" namespace nice { //通常,应该作为一种策略被组合到对象上,而不是继承树的基类 //因此virtual public继承常常是必要的. struct non_ref_count{}; class ref_count //被组合对象将通过delete来释放,因此,对象的分配必须能够满足此要求。 //这在1.使用allocator策略时,可能导致问题。 // 2.不可以使用stack对象 // 3.不可是数组成员,本身也不可以是数组,但可以是容器 { public://publishing interface ref_count() : count_(0){} virtual ~ref_count() {} //default ctor && assignment int add_ref() { return ++count_; }; int release() { int tmp = --count_; if (tmp == 0) delete this; return tmp; } public://queries int count() const { return count_; } private: int count_; };
template<typename _ins_type> class ref_count_ptr { public: typedef _ins_typeins_type; ref_count_ptr() : obj_(0){}; ~ref_count_ptr() { release(); }
ref_count_ptr(const ref_count_ptr& rhs) : obj_(rhs.obj_) { inc(); }
ref_count_ptr& operator=(const ref_count_ptr& rhs) { refrence(rhs.obj_); return *this; }
ins_type* refrence() const { return obj_; }
void refrence(ins_type* obj) { if (obj == obj_) return;
release();
obj_ = obj; inc(); } ins_type* operator->() const { pre_condition(!is_null(), "derefrence Null pointer"); return obj_; } ins_type& operator*() const { pre_condition(!is_null(), "derefrence Null pointer"); return *obj_; } bool is_null() const { return obj_ == 0; } #define MEMBER_OPE(ope)/ inline bool operator ope (const ref_count_ptr& rhs) const/ {/ return obj_ ope rhs.obj_;/ } MEMBER_OPE(==) MEMBER_OPE(!=) MEMBER_OPE(<) MEMBER_OPE(<=) MEMBER_OPE(>) MEMBER_OPE(>=) #undef MEMBER_OPE private: void release() { obj_ != 0 && obj_->release(); } void inc() { if (obj_ != 0) obj_->add_ref(); } ins_type* obj_; };
template<typename ins_type, typename ref_count_ = ref_count> class assembler : public ins_type , public ref_count_//没有virtual, 因此,派生需小心,不要再引入ref_count //不使用virtual是为了效率, { public: assembler(){} assembler(const ins_type& obj, const ref_count_& ref = ref_count_()) : ins_type(obj), ref_count_(ref) {} assembler(const assembler& rhs) : ins_type(rhs), ref_count_() {} assembler& operator=(const assembler& rhs) { ins_type::operator=(rhs); return *this; } }; } //namespace nice
#endif //end REFCOUNT_H guard