引用计数,写时复制(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类的声明如下:
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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);
};
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);
};
定义如下:
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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;
}
: 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];
}
{
// 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) 编辑 收藏 举报