引用计数的工作方式:
-
除了初始化对象外,每个构造函数(除拷贝构造函数外)还要创建一个引用计数,用来记录有多少对象与正在创建的对象共享状态。当我们创建一个对象时,只有一个对象共享状态,因此将计数器初始化为1。
-
拷贝构造函数不分配新的计数器,而是拷贝给定对象的数据成员,包括计数器。拷贝构造函数递增共享的计数器,指出给定对象的状态又被一个新用户共享。
-
析构函数递减计数器,指出共享状态的用户少了一个。如果计数器变为0,则析构函数释放状态。
-
拷贝赋值运算符递增右侧运算对象的计数器,递减左侧运算对象的计数器。如果左侧运算对象的计数器变为0,意味着它的共享状态没有用户了,拷贝赋值运算符就必须销毁状态。
我们可以通过在动态内存中保存计数器的方法来解决在哪里存放引用计数的问题。这里注意 大多数赋值运算符组合了析构函数和拷贝构造函数的工作 这一特点。
class HasPtr
{
public:
HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0),
use_count(new std::size_t(1))
{}
HasPtr(const HasPtr &p) : ps(p.ps), i(p.i), use_count(p.use_count)
{
++*use_count;
}
~HasPtr();
HasPtr& operator=(const HasPtr&p);
private:
std::string *ps;
int i;
std::size_t *use_count;
};
其实现部分:
HasPtr::~HasPtr()
{
if (--*use_count == 0) {
delete ps;
delete use_count;
}
}
HasPtr &HasPtr::operator=(const HasPtr &p)
{
++*p.use_count;
// like析构函数
if (--*use_count == 0) {
delete ps;
delete use_count;
}
// like拷贝构造函数
ps = p.ps;
i = p.i;
use_count = p.use_count;
return *this;
}
网友评论