CopyOnWrite实现引用计数String类

//引用计数基类
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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值