在程序中为了提高性能,降低程序的内存使用量。可以使用引用计数技术。
该技术的详细可以参见《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类的声明如下:
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);
};
定义如下:
: 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)可以解决这个问题。
可以对[] 操作符的重载,如下:
代码
{
// 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中这么用,可以作为基类,让所有的子类都有此功能,当然不是那么简单,在这过程中 还要用灵巧指针。