徐州建设网站公司,万国商业网,装饰公司网站源码下载,无锡市锡山建设局网站Reference counting的两个技术动机#xff1a;
为了简化heap objects周边的簿记工作#xff0c;当对象运用了引用计数技术#xff0c;一旦不再有任何人使用它#xff0c;它便自动销毁自己#xff0c;也因此#xff0c;reference counting建构出垃圾回收机制的一个简单形…Reference counting的两个技术动机
为了简化heap objects周边的簿记工作当对象运用了引用计数技术一旦不再有任何人使用它它便自动销毁自己也因此reference counting建构出垃圾回收机制的一个简单形式为了实现一种常识。如果许多对象有相同的值将那个值存储多次是一件愚蠢的事最好是让所有等值对象共享一份实值即可不仅节省内存也会使得程序速度加快因为不再需要构造和析构同值对象的多余副本。
由于需要记录“目前共享同一实值”的对象个数一个reference count引用计数器就此引入
Reference Counting引用计数 的实现
我们需要为每一个字符串值准备一个引用计数而不是为每一个字符串对象准备暗示了“对象值”和“引用计数”之间有一种耦合关系产生一个class不但存储引用计数也存储它们追踪的对象值
class String
{
public:... //一般的String成员函数安排在这里
private:struct StringValue{...}; //持有一个引用次数以及一个字符串值StringValue* value; //String的值
};//String的定义
class String
{
private:struct StringValue{int refCount;char* data;};StringValue(const char* initValue);~StringValue();...
};//StringValue提供一个地点
//将某特定值以及共享该值的String对象个数关联起来。
String::StringValue::StringValue(const char* initValue):refCount(1)
{data new char[strlen(initValue) 1];strcpy(data,initValue);
}String::StringValue::~StringValue()
{delete [] data;
}//String的成员函数从构造函数开始
class String
{
public:String(const char* initValue );String(const String rhs);...
};//传入char*创建一个新的StringValue对象
String::String(const char* initValue) : value(new StringValue(initValue));
{}//String的复制构造函数很有效率
String::String(const String rhs):value(rhs.value)
{value - refCount;
}//运用
String s1(More Effective C);
String s2(s1);
//新生成的String对象与被复制的对象共享相同的StringValue对象以上只需将指针复制一份并将引用从次数加1不需要分配和归还内存效率更高。
//String的析构函数
class String
{
public:~String();
};
String::~String()
{if(--value-refCount 0) delete value;//只有当唯一的用户被析构String析构函数才销毁StringValue
}//String的赋值操作符
class String
{
public:...String operator (const String rhs);
};String String::operator (const String rhs)
{if(value rhs.value)return *this;if(--value-refCount 0)delete value;value rhs.value;value-refCount;return *this;
}Copy-On-Write写时才复制
方括号操作符[ ]它允许字符串中的个别字符被读取或被写
class String
{
public:const char operator[](int index) const;//针对const Stringschar operator[](int index); //针对non-const String...
};//const版本只读动作字符串内容不受影响
const char String::operator[](int index) const
{return value-data[index];
}//non-const版本
//可能用来读取一个字符串也可能用来写一个字符串
String s;
...
cout s[3]; //读取动作
s[5] x; //写入动作为了安全实现出non-const operator[]我们必须确保没有其他任何“共享同一个StringValue”的String对象因写动作而改变
char String::operator[](int index)
{//如果本对象和其他String对象共享同一实值//就分割复制出另一副本供本对象自己使用if(value-refCount 1)--value-refCount; //将目前实值的引用频次减1因为我们不再使用//为自己做一份新的副本value new StringValue(value-data);//返回一个reference代表我们这个“绝对不被共享”的//StringValue对象内的一个字符。return value-data[index];
}PointersReferences以及Copy-On-Write
为每一个StringValue对象加上一个标志flag变量用以指示可否被共享
//修改版
class String
{
private:struct StringValue{int refCount;bool shareable; //新增此行char* data;};StringValue(const char* initValue);~StringValue();...
};String::StringValue::StringValue(const char* initValue):refCount(1),shareable(true)//新增此行
{data new char[strlen(initValue) 1];strcpy(data,initValue);
}String::StringValue::~StringValue()
{delete [] data;
}//复制函数的新行为
String::String(const String rhs)
{if(rhs.value-shareable){value rhs.value;value-refCount;}else{value new StringValue(rhs.value-data);}
}//Non-const operator[]是唯一将shareble设为false者
char String::operator[](int index)
{if(value-refCount 1)--value-refCount;value new StringValue(value-data);value-shareable false; //新增此行return value-data[index];
}一个Reference-Counting引用计数基类
Reference-counting可用于字符串以外的场合任何class如果其不同的对象可能拥有相同的值都适用此技术。
产生一个base class RCObject作为“reference-counted对象”之用。 任何class希望自动拥有reference counting能力都必须继承自这个类
//RCObject定义
class RCObject
{
public:RCObject();RCObject(const RCObject rhs);RCObject operator (const RCObject rhs);virtual ~RCObject() 0;void addReference();void removeReference();void markUnshareable();bool isShareable() const;bool isShared() const;private:int refCount;bool shareable;
};//RCObject实现
RCObject::RCObject():refCount(0),shareable(true){}RCObject::RCObject(const RCObject rhs):refCount(0),shareable(true){}RCObject RCObject::operator (const RCObject rhs)
{ return *this; }RCObject::~RCObject(){}void RCObject::addReference()
{refCount;
}void RCObject::removeReference()
{if(--refCount 0)delete this;
}void RCObject::markUnshareable()
{shareable false;
}bool RCObject::isShareable() const
{return shareable;
}bool RCObject::isShared() const
{return refCount 1;
}//StringValue继承自RCObject
class String
{
private://StringValue的成员函数不再处理refCount字段改由RCObject掌管struct StringValue: public RCObject{char* data;StringValue(const char* initValue);~StringValue();};...
};String::StringValue::StringValue(const char* initValue)
{data new char[strlen(initValue) 1];stpcpy(data,initValue);
}String::StringValue::~StringValue()
{delete [] data;
}自动操作Reference Count引用次数
我们希望能够把这一系列调用动作移到一个可复用的class内这么一来可以让诸如String之类的classes的作者不必操心reference counting的任何细节。
//下面这个模板用来产生智能指针指向reference-counted对象
templateclass T
class RCPtr
{
public:RCPtr(T* realPtr 0);RCPtr(const RCPtr rhs);~RCPtr();RCPtr operator (const RCPtr rhs);T* operator-() const;T operator*() const;private:T* pointee;void init();
};//实现
templateT
RCPtrT::RCPtr(T* realPtr 0):pointee(realPtr)
{init();
}templateT
RCPtrT::RCPtr(const RCPtr rhs)pointee(rhs.pointee)
{init();
}templateT
void RCPtrT::init()
{if(pointee NULL) return ; if(pointee-isShareble() false)pointee new T(*pointee);pointee-addReference();
}以上错误在于init pointee new T(*pointee)构造新的T对象但是RCPtr在String类内部T将是String::StringValue所以我们必须为String::StringValue加上深复制函数
class String
{
private:struct StringValue: public RCObject{StringValue(const StringValue rhs);...};
};String::StringValue::StringValue(const StringValue rhs)
{data new char[strlen(rhs.data) 1];strcpy(data,rhs.data);
}把所有努力放在一起
templateclass T //template class用来产生
class RCPtr //smart pointers-to-Tobjects
{ //T必须继承自RCObject
public:RCPtr(T* realPtr 0);RCPtr(const RCPtr rhs);~RCPtr();RCPtr operator (const RCPtr rhs);T* operator-() const;T operator*() const;private:T* pointee;void init();
};class RCObject //base class, 用于reference-counted objects
{
public:void addReference();void removeReference();void markUnshanreable();bool isShareable() const;bool isShared() const;protected:RCObject();RCObject(const RCObject rhs);RCObject operator (const RCObject rhs);virtual ~RCObject() 0;private:int refCount;bool shareable;
};class String //应用性class这是应用程序开发人员接触的层面
{
public:String(const char* value );const char operator[](int index) const;char operator[](int index);private:struct StringValue: public RCObject{char* data;StringValue(const char* initValue);StringValue(const StringValue rhs);void init(const char* initValue);~StringValue();};RCPtrStringValue value;
};//RCObject实现
RCObject::RCObject():refCount(0),shareable(true){}RCObject::RCObject(const RCObject rhs):refCount(0),shareable(true){}RCObject RCObject::operator (const RCObject rhs)
{ return *this; }RCObject::~RCObject(){}void RCObject::addReference()
{ refCount; }
void RCObject::removeReference()
{if(--refCount 0)delete this;
}void RCObject::markUnshanreable()
{ shareable false; }
bool RCObject::isShareable() const
{return shareable;
}
bool RCObject::isShared() const
{return refCount 1;
}//RCPtr实现
templateclass T
void RCPtrT::init()
{if(pointee 0) return;if(pointee-isShareable false)pointee new T(*pointee);pointee-addReference;
}templateclass T
RCPtrT::RCPtr(T* realPtr 0):pointee(realPtr)
{ init();
}templateclass T
RCPtrT::RCPtr(const RCPtr rhs):pointee(realPtr)
{init();
}templateclass T
RCPtrT::~RCPtr()
{if(pointee)pointee-removeReference();
}templateclass T
RCPtr RCPtrT::operator (const RCPtr rhs)
{if(pointee ! rhs.pointee){if(pointee)pointee-removeReference();pointee rhs.pointee;init();}return *this;
}templateclass T
T* RCPtrT::operator-() const
{ return pointee; }templateclass T
T RCPtrT::operator*() const
{ return *pointee; }//String::StringValue实现
void String::StringValue::init(const char* initValue)
{data new char[strlen(initValue) 1];strcpy(data,initValue);
}String::StringValue::StringValue(const char* initValue)
{init(initValue);
}
String::StringValue::StringValue(const StringValue rhs)
{init(rhs.data);
}String::StringValue::~StringValue()
{delete [] data;
}//String实现
String::String(const char* value )value(new StringValue(initValue)){}const char String::operator[](int index) const
{return value-data[index];
}
char String::operator[](int index)
{if(value-isShared()){value new StringValue(value-data);}value-markUnshanreable();return value-data[index];
}将Reference Counting加到既有的Classes身上
就像“StringValue只能实现细节不需让String的用户知道”一样 CountHolder也是实现细节不需让RCWidget的用户知道。 事实上它是RCIPtr的实现细节所以嵌套放入RCIPtr class内部。
RCIPtr实现如下
templateclass T
class RCIPtr
{
public:RCIPtr(T* realPtr 0);RCIPtr(const RCIPtr rhs);~RCIPtr();RCIPtr operator (const RCIPtr rhs);const T* operator-() const;T* operator-();const T operator*() const;T operator*();
private:struct CountHolder: public RCObject{~CountHolder{ delete pointee; }T* pointee;};CountHolder* counter;void init();void makeCopy();
};templateclass T
void RCIPtrT::init()
{if(counter-isShareable false){T* oldValue counter-pointee;counter new CountHolder;counter-pointee new T(*pointee);} pointee-addReference;
}templateclass T
RCIPtrT::RCIPtr(T* realPtr):counter(new CountHolder)
{counter-pointee realPtr;init();
}templateclass T
RCIPtrT::RCIPtr(const RCIPtr rhs):counter(rhs.counter)
{init();
}templateclass T
RCIPtrT::~RCIPtr()
{counter-removeReference;
}templateclass T
RCIPtr RCIPtrT::operator (const RCIPtr rhs)
{if(counter ! rhs.counter){counter-removeReference();counter rhs.counter;init();}return *this;
}templateclass T
const T* RCIPtrT::operator-() const
{return counter-pointee;
}templateclass T
const T RCIPtrT::operator*() const
{return *(counter-pointee);
}总结
什么时候最适合reference counting技术
相对多数的对象共享相对少了的实值对象实值的产生或销毁成本很高或使它们使用许多内存。