写时拷贝(copy on write)

        适用于深拷贝提高效率的一种方法。

        例如string类,在拷贝构造时,会要用到深拷贝。如果用浅拷贝,会导致两对象的指针指向同一块空间,导致对象析构时,导致同一块空间释放两次,程序奔溃。深拷贝是在对象再开一块空间,将值拷贝过去,再让新对象的指针指向新开辟的空间。

        深拷贝运用写时拷贝时,不会立马申请空间。它是一开始先让新的对象的指针先同时指向同一块空间。在读的时候或者是写的时候再在堆上申请空间给对象。

        这里引入了一个引用计数:用来记录资源使用者的个数。在构造时,将计数给为1,没增加一个对象指向这块空间计数加1(指向的是同一块空间)。当销毁时计数减1,然后再检查是否需要释放该资源(之前对象都指向的空间),如果计数为1,则可以释放,否则不可以释放。

        当是写时拷贝有一个缺陷,如果用户读对象的值的时候,写时拷贝就失效了,也会直接开辟新空间。    

//构造函数(分存内存)
string::string(const char* tmp)
{
	_Len = strlen(tmp);
	_Ptr = new char[_Len + 1 + 1];
	strcpy(_Ptr, tmp);
	_Ptr[_Len + 1] = 0;  // 设置引用计数  
}

//拷贝构造(共享内存)
string::string(const string& str)
{
	if (*this != str){
		this->_Ptr = str.c_str();   //共享内存
		this->_Len = str.szie();
		this->_Ptr[_Len + 1] ++;  //引用计数加一
	}
}

//写时才拷贝Copy-On-Write
char& string::operator[](unsigned int idx)
{
	if (idx > _Len || _Ptr == 0) {
		static char nullchar = 0;
		return nullchar;
	}

	_Ptr[_Len + 1]--;   //引用计数减一
	char* tmp = new char[_Len + 1 + 1];
	strncpy(tmp, _Ptr, _Len + 1);
	_Ptr = tmp;
	_Ptr[_Len + 1] = 0; // 设置新的共享内存的引用计数

	return _Ptr[idx];
}

//析构函数的一些处理
~string()
{
	_Ptr[_Len + 1]--;   //引用计数减一

	// 引用计数为0时,释放内存 
	if (_Ptr[_Len + 1] == 0) {
		delete[] _Ptr;
	}

}

参考:https://coolshell.cn/articles/12199.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值