一、写时拷贝的引入
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;
}