引用计数,写时复制(Copy On Write)

在程序中为了提高性能,降低程序的内存使用量。可以使用引用计数技术。

该技术的详细可以参见《More Effective C++》的条款29。

在没有使用引用计数的String类中如果写下如下语句: 

 String a, b, c;

a = b = c = "Hello";

a ,b,c3个对象中都有“Hello”字符串。

如果 a,b,c都指向同一个"Hello"字符串就能节省内存。

因此可以使用引用计数来对对象copy时进行(count++),对象删除时(count--), 

所以在String对象中需要增加一个count变量。

使用了引用计数后的String类的声明如下: 

代码
class String {
private:
    
struct StringValue {
      
int refCount;
      
char *data;
      StringValue(
const char *initValue);
      
~StringValue();
    };
    StringValue 
*value;
public:
    String(
const char *initValue = "");
    String(
const String& rhs);
    
~String();
    String
& operator=(const String& rhs);

};

 定义如下:

代码
String::StringValue::StringValue(const char *initValue)
: refCount(
1)
{
  data 
= new char[strlen(initValue) + 1];
  strcpy(data, initValue);
}
String::StringValue::
~StringValue()
{
  delete [] data;
}


String::String(
const char *initValue)
: value(
new StringValue(initValue))
{}

String::String(
const String& rhs)
: value(rhs.value)
{

  
++value->refCount;
}

String::
~String()
{
  
if (--value->refCount == 0
  delete value;
}

String
& String::operator=(const String& rhs)
{
  
if (value == rhs.value) {          // do nothing if the values
    return *this;                    // are already the same; this
  }                                  // subsumes the usual test of
                                     
// this against &rhs (see Item E17)
  if (--value->refCount == 0) {      // destroy *this's value if
    delete value;                    // no one else is using it
  }
  value 
= rhs.value;                 // have *this share rhs's
  ++value->refCount;                 // value
  return *this;
}

  但是,如果上述的a,b,c如果有一个对象要想改变值时,例如:

a[2]  = 'a';

由于共享一份内存,因此其他的变量的值也会被修改。

 没关系,写时拷贝(Copy on Write)可以解决这个问题。

可以对[] 操作符的重载,如下:

 代码

char& String::operator[](int index)
{
  
// if we're sharing a value with other String objects,
  
// break off a separate copy of the value for ourselves
  if (value->refCount > 1) {
    
--value->refCount;                    // decrement current value's
                                          
// refCount, because we won't
                                          
// be using that value any more
    value =                               // make a copy of the
      new StringValue(value->data);       // value for ourselves
  }
  
// return a reference to a character inside our
  
// unshared StringValue object
  return value->data[index];
}

 

 

 但是虽然这么做,在下面的这种情况下还是可能会出现问题:

String s1 = "Hello";

char *p = &s1[1]; 

String s2 =  s1 ;

这种情况可以通过Flag来控制,具体不多说了,参考ITEM29

引用计数和写时拷贝技术不但在String中这么用,可以作为基类,让所有的子类都有此功能,当然不是那么简单,在这过程中 还要用灵巧指针。 

 

 

posted on 2009-12-05 21:20  browser_fans  阅读(500)  评论(0编辑  收藏  举报

导航