写时拷贝的方式实现C++中string类

本文介绍了如何在C++中利用写时拷贝(Copy-On-Write, COW)技术来优化String类的实现。通过写时拷贝,可以避免不必要的内存开销,提高效率。文章首先提出问题,即在创建多个对象但未修改时,不必要的内存分配。然后解释了写时拷贝的概念,即只有在尝试修改对象时才真正复制内存。最后,给出了一个简单的实现,将计数器与字符串数据存储在同一个分配的空间中。" 4542006,411072,C++编程获取CPU和内存使用率,"['编程', '性能监控', 'C++开发', '系统信息']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、写时拷贝的引入

class String
{
	friend ostream& operator<<(ostream& os,const String& s);
public:
	String(const char* s)
		:_str(new char[strlen(s)+1])
	{
		strcpy(_str,s);
	}
	//深拷贝
	String(String& s)		//拷贝构造
		:_str(new char[strlen(s)+1])
	{
		strcpy(_str,s._str);
	}
private:
	char* _str;
};
void test1()
{
	String str1("abcde");
	String str2(str1);
	cout<<str1<<endl;
	cout<<str2<<endl;
}

这个String类中只简单实现了构造函数和拷贝构造函数,很明显可以看出,在创建str1和str2时都开辟了空间。但是对于str2,只是单纯的使用了它并将str2所指向的内容输出,并没有操作这块空间,因此给str2开辟空间会显得有点浪费。这时就可以引用写时拷贝的方式。

二、什么是写时拷贝?

顾名思义,写时拷贝就是在需要修改这块空间的内容时才分配一块空间。同样用上边的例子,写时拷贝会存在一个计数器,并且多个对象指向同一块空间,每次创建一个新的对象时,计数器++,销毁时计数器 - - (具体代码如下:)


实现一:

//计数器
class String
{
	friend ostream& operator<<(ostream& os,const String& s);
public:
	String(const char* s = "")
		:_str(new char[strlen(s)+1])
		,_pCount(new int(1))
	{
		cout<<"gouzao"<<endl;
		strcpy(_str,s);
	}
	String(String& s)		//拷贝构造
		:_str(s._str)
		,_pCount(s._pCount)
	{
		cout<<"kaobeigouzao"<<endl;
		++ *_pCount;
	}
	~String()
	{
		if(--_pCount[0] == 0)
		{
			cout<<"~String()"<<endl;
			delete[] _str;
			delete _pCount;
		}
	}
	String& operator = (const String& s)
	{
		_str = s._str;
		_pCount = s._pCount;
		if (this != &s)		//检测是否自赋值
		{
			if(--*_pCount == 0)
			{
				delete[] _str;
				_str = new char[strlen(s._str)+1];
				strcpy(_str,s._str);
			}
		}
		return *this;
	}
private:
	char* _str;
	int* _pCount;
};
ostream& operator<<(ostream& os,const String& s)
{
	os<<s._str<<endl;
	return os;
}
void test()
{
	String str1("abcde");
	String str2(str1);
	String str3;
	str3 = str2;
	cout<<str1<<endl;
	cout<<str2<<endl;
	cout<<str3<<endl;
}
实现二:

将_pCount与_str所指向的空间放在一起,即只用new开辟一次空间


class String
{
	friend ostream& operator<<(ostream& os,String& s);
public:
	String(const char*str = "")
		:_str(new char[strlen(str)+1+4])
	{
		*(int *)_str = 1;	//*_pCount = 1
		_str = _str+4;	//找到数据存放的位置
		strcpy(_str,str);
		GetCount() = 1;
	}
	String(const String& str)
		:_str(str._str)
	{
		++GetCount();
	}
	~String()
	{
		if(--GetCount() == 0)
		{
			delete[] (_str-4);
		}
	}
	String& operator=(const String& s)
	{
		if (this != &s)
		{
			if (--GetCount() == 0)
			{
				delete[] (_str-4);  
			}
			++GetCount();
			_str = s._str;
		}
		return *this;
	}
private:
	int& GetCount()		//获得_pCount
	{
		return *((int *)_str-1);
	}
private:
	char *_str;
};
ostream& operator<<(ostream& os,String& s)
{
	os<<s._str;
	return os;
}
void test1()
{
	String str1("abcde");
	String str2(str1);
	String str3;
	str3 = str2;
	cout<<str1<<endl;
	cout<<str2<<endl;
	cout<<str3<<endl;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值