引用计数型指针类的一个实现
2004-06-30 17:00
218 查看
这是一段引用计数指针的代码,目标是一个轻量级的、高效率的实现,避免通常实现中的频繁的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_type ins_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
一些说明:
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_type ins_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
相关文章推荐
- 自己实现一个带引用计数的智能指针,根据源码
- 利用虚引用PhantomReference实现对象被回收时收到一个系统通知
- 编写一个智能指针类,自动记录SmartPointer<T*>对象的引用计数,一旦T类型对象的引用计数为零,就会释放对象
- 引用计数型String类的简单实现
- 实现一个智能指针类
- @Resource引用一个bean时,为什么要声明接口而不是实现类?
- 引用js文件时src=可传递参数,实现在一个js中引用另一个js文件
- 原生js实现的下拉多选控件,引用只需一个js
- Spring实现一个singleton bean要引用另外一个非singleton bean
- VB 实现大文件的分割与恢复,引用 ADODB.Stream 提供一个过程代码
- 一个weak引用NSArray的实现
- 引用js文件时src=可传递参数,实现在一个js中引用另一个js文件
- 怎么实现一个站点的list列引用另外一个站点的list列数据?
- 引用计数型String类的简单实现
- C++开发中一个解决方案里,两个项目的相互引用,相互依赖的实现方法(解决方法)
- 设计一个函数,既能计算圆的周长也能计算圆的面积(分别用指针和引用实现)
- VB 实现大文件的分割与恢复,引用 ADODB.Stream 提供一个过程代码
- 引用计数型指针的的简单实现
- 如何实现一个带引用记数的智能指针模板
- 泛型实现中没有正确lock引用类型的一个隐藏bug分析