写时拷贝 code

写时拷贝解决2个问题:
1.析构多次
2.修改一个对象会影响其他变量

设置引用计数后,当一个对象析构,引用计数-1,没有减到0就不释放空间,能够解决问题1.
当对字符串进行修改时,判断其引用计数是否大于1(大于1说明至少2个对象指向该串,贸然修改就会出现问题2),此时使用剥削手法,为要修改的对象分配同样的空间,另外操作,即可解决问题2.

class String
{
public:
	
	int& GetRefCount()//取到头部的4个字节,方便赋值
	{
		return (*(int*)(str - 4));
	}

	String(const char *_str="")//构造函数,str头部多开4个字节来存储引用计数,
		:str(new char [strlen(_str)+5])//5中  4个字节存引用计数,1个字节存'\0'
	{
		str += 4;
		strcpy(str, _str);
		GetRefCount() = 1;

	}

	String(const String &s)//拷贝构造,只需让新对象的指针指向被拷对象的str,并让引用计数+1即可
		:str(s.str)
	{
		GetRefCount()++;
	}

	String& operator=(const String& s)//赋值运算符重载,返回值为string&可以连等
	{
		if (str != s.str)//防止出现s1=s1的情况
		{
			if (--GetRefCount() == 0)
			{
				delete[](str - 4);
			}
			str = s.str;
			GetRefCount()++;
		}
		return *this;

	}

	
	void copy_on_write()//判断修改对象字符串时会不会影响到其他对象
	{
		if (GetRefCount() > 1)//如果有不止1个对象指向该字符串,那么就要另外开辟空间
		{
			String tmp(str);//剥削手段
			swap(str, tmp.str);
			GetRefCount() = 1;
		}//对象tmp析构,不会影响s1对象
	}
		
	char* c_str()
	{
		return str;
	}
	
	char& operator[](size_t pos)
	{
		copy_on_write();
		return str[pos];
	}

	~String()
	{
		if (--GetRefCount() == 0)//说明当前析构的对象是最后一个指向该串的对象
		{
			delete[](str - 4);
		}
	}
private:
	char *str;
};
int main()
{
	String s1("hello");
	String s2(s1);
	s2[0] = 'x';
	String s3("world");
	s3 = s1;


	return 0;
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值