引用计数

什么是引用计数?

一个在堆上创建的对象,记录有多少个指针指向它。


 为什么要设计引用计数,他解决什么问题?

1、new出一个临时对象,使用完了,需要delete。但是拥有权会转移(auto_ptr)或者扩散,因此很难确定delete时机。忘记delete导致资源泄漏,过早delete,导致还在使用的指针出现错误,重复delete导致未定义行为。

2、许多对象拥有相同的值,存储多次是个很愚蠢的事,可以共享。


如何实现:

1、以String为例说明,String s1 = "Hello", String s2 = s1; 可以让s1,s2共享"Hello"。

2、引用计数放在哪里呢?显然不能放在String对象中,因为每个String对象都有这个引用计数,引用计数应该和String指向的Value在一起。

3、在String中建立一个嵌套类StringValue,String中有一个字段 StringValue* pStringValue。为什么StringValue设计成嵌套类,因为StringValue只是嵌套在String中,为了实现String,不会出现在其他地方。与此类似的有,STL中各种容器专属的迭代器。

4、StringValue中有:int refCount,记录引用计数。char* pData:指向char。

5、String的copy构造

1 String::String(const String& rhs)
2     :pStringValue(rhs.pStringValue)
3 {
4     ++(pStringValue->refCount);
5 }

6、String的copy赋值

 1 String& String::operator =(const String& rhs)
 2 {
 3     if(pStringValue == rhs.pStringValue) //共享的数据赋值
 4     {
 5         return *this;
 6     }
 7     
 8     if(--pStringValue->refCount == 0) //处理老的内容
 9     {
10         delete pStringValue;
11     }
12     
13     pStringValue = rhs.pStringValue;
14     ++pStringValue->refCount;
15     
16     return *this;
17 }

7、String的析构

1 String::~String()
2 {
3     if(--pStringValue->refCount == 0)
4     {
5         delete pStringValue;
6     }    
7 }

8、Copy-On-Write(写时才复制)

考虑s1,s2指向同一个内容,s1[2] = f; 程序员期望只是修改s1,如何支持?

 1 char& operator[](int index)
 2 {
 3     if(this->pStringValue->refCount > 1) //存在其他人共享
 4     {
 5         --this->pStringValue->refCount;
 6         this->pStringValue = new StringValue(pStringValue->pData);
 7     }
 8     
 9     return pStringValue->pData[index];
10 }

9、考虑 char* pc = &s1[2]; 然后修改pc,还是会修改s2,怎么办?
  增加一个标志位,访问[],设置StringValue不是共享。

10、现在假如Person,Book也有这种需求,怎么办?

  需要建立PersonValue,BookValue,通过建立基类,复用代码。RCValue为基类,RCValue 的copy构造和copy赋值,不需要做任何事,因为不会对RCValue调用copy构造和copy赋值。而是对String,Person,Book调用copy构造,copy赋值,传递pValue指针。

11、对于String中的pStringValue使用smart point,可以实现自动操作引用计数。

posted on 2013-12-02 20:45  Andy Niu  阅读(1348)  评论(0编辑  收藏  举报