一、写时拷贝的引入

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;
}



本文转载:CSDN博客