//引用计数基类
class RefBase
{
public:
RefBase() {}
RefBase(const RefBase& rhs) {}//计数对象copy不做任何操作
RefBase& operator =(const RefBase& rhs) { return *this; }//计数对象copy不做任何操作
virtual ~RefBase() = 0
{
}
//增加原始数据被引用的计数
void addRef() {
++RefCount;
}
//减少原始数据被引用的计数 若引用个数为0 则删除原始数据
void removeRef() {
if(--RefCount==0)
delete this;
}
//使引用数据变为不可共享状态
void marUnShareable(){
shareable = false;
}
//查询当前引用数据的共享状态
bool IsShareable(){
return shareable;
}
//引用数据是否已经被共享
bool IsShared() {
return RefCount > 1;
}
private:
int RefCount = 0; //引用计数
bool shareable = true;//共享状态
};
//操作引用计数的smart ptr
template<typename T>
class rfPtr
{
public:
explicit rfPtr(T* realptr):pointer(realptr)//初始化列表先直接指向想要引用的对象
{
init();//判断引用对象是否可以直接引用还是必须拷贝引用对象
}
rfPtr(const rfPtr& rhs):pointer(rhs.pointer)//初始化列表先直接指向想要引用的对象
{
init();//判断引用对象是否可以直接引用还是必须拷贝引用对象
}
~rfPtr()
{
if (pointer)
pointer->removeRef();//析构时对其引用对象进行引用计数判断 引用计数为0在真正析构引用对象
}
rfPtr& operator =(const rfPtr& rhs)
{
if (pointer != rhs.pointer)
{
if (pointer){
pointer->removeRef(); //拷贝复制操作 先要将原来指向的引用对象 进行减计数操作
}
pointer = rhs.pointer;//先直接指向想要引用的对象
init();//判断引用对象是否可以直接引用还是必须拷贝引用对象
}
return *this;
}
rfPtr& operator =(T* rhs)//避免隐式构造临时rfPtr对象
{
if (pointer == rhs)
return*this;
if (pointer) {
pointer->removeRef(); //拷贝复制操作 先要将原来指向的引用对象 进行减计数操作
}
pointer = rhs;
init();
}
T* operator->() const
{
return pointer;
}
T& operator*() const
{
return *pointer;
}
private:
T* pointer;//指向一个引用对象
void init()
{
if (pointer == nullptr)
return;
//如果引用的引用对象不是共享状态 则必须构造一个新的引用对象
if (pointer->IsShareable() == false)
pointer=new T(*pointer);//新构造的引用对象要执行深拷贝
pointer->addRef();//无论是引用上一个引用对象或者构造新的引用对象 引用计数加1
}
};
//引用计数的String
class String
{
public:
//String直接用编译器隐式提供的拷贝构造,拷贝复制
String(const char* realvalue = ""):value(new CRefVal(realvalue)){}//单参构造函数 一步步调用rfPtr与CRefVal构造函数
char& operator [](int nIndex){
if (value->IsShared())//可能写入操作时 若引用的对象已经被多个String引用则 复制一份引用对象用于String写操作
{
value = new CRefVal(value->data);
}
value->marUnShareable();//当前String 丧失引用对象共享状态
return value->data[nIndex];
}
const char& operator [](int nIndex) const {
return value->data[nIndex];
}
private:
//引用计数类 保存了真实数据 引用计数类就是对原始数据的封装
struct CRefVal : public RefBase
{
char* data;//指向真实数据
CRefVal(const char* inivalue)//构造引用对象
{
init(inivalue);
}
CRefVal(const CRefVal& rhs)//构造引用对象
{
init(rhs.data);
}
//引用对象本书必须提供内存保存原始数据
void init(const char* inivalue) {
data = new char[strlen(inivalue) + 1];
strcpy(data, inivalue);
}
private:
~CRefVal() { //引用对象本身释放必须释放原始数据
delete[] data;
}
};
rfPtr<CRefVal> value;
};
int main()
{
String mstr("tianshi");
String tstr("jiangkai");
String mstr1(mstr);
String mstr2(mstr);
mstr1=tstr;
mstr2 = "yangkang";
mstr1[1] = 'P';
return 0;
}
CopyOnWrite实现引用计数String类
最新推荐文章于 2023-11-14 13:31:55 发布