写时才拷贝(Copy-On-Write)的原理是什么?
Copy-On-Write,其实是使用了一个计数器。当第一个类构造时,计数器初始值为1,string类的构造函数会根据传入的参数从堆上分配内存,当其他类需要这块内存时,这个计数器自动累加。当有析构函数时,这个计数器会减1,直到当计数器为1时,即最后一个类析构。此时,程序才会真正的delete这块从堆上分配的内存。
2. string在什么情况下会发生写时才拷贝(Copy-On-Write)?
当string类中发生内存共享且内容发生改变时,会触发写时才拷贝(Copy-On-Write)。比如string类的[]、=、+=、+操作符。
3. string类在什么情况下会发生内存共享?
如果一个类需要用另一个类的数据,那就可以共享被使用类的内存了。
使用别的类的数据时,有两种情况:
(1)用别的类构造自己;调用拷贝构造函数。
(2)以别的类赋值;调用重载赋值操作符函数。
4. 写时才拷贝的实现:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class String
{
public:
String(char* str = "")
:_str(new char[strlen(str)+1])
,_pcount(new int(1))
{
strcpy(_str,str);
}
~String()
{
if(_str != NULL)
{
if(--*_pcount == 0)
{
delete[] _str;
delete _pcount;
}
}
}
String(const String& str)
{
_str = str._str;
_pcount = str._pcount;
++(*_pcount);
}
String& operator=(const String& str)
{
if(this != &str)
{
if(--(*_pcount) == 0)
{
delete[] _str;
delete _pcount;
}
_str = str._str;
_pcount = str._pcount;
++(*_pcount);
}
return *this;
}
private:
char* _str;
int* _pcount;
};
int main()
{
String str1("hello");
String str2(str1);
String str3;
str3 = str1;
return 0;
}
注:str1,str2,str3共享同一块内存。
string类都是在堆上动态开辟空间的,我们在开辟空间的同时多开辟一个整型空间来存放计数器。所有共享同一个内存的类都使用同一个计数器。
实现:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class String
{
public:
String(char *str = "")
:_str(new char[strlen(str)+5])
{
*(int *)_str = 1;
_str += 4;
strcpy(_str,str);
}
~String()
{
if(_str != NULL)
{
if(--*(int *)(_str-4)==0)
{
delete[] (_str-4);
}
}
}
String(String& str)//拷贝构造
{
_str = str._str;
++*(int *)(_str-4);
}
String& operator=(String &str)
{
if(this != &str)
{
if(--*(int *)(_str-4) == 0)
{
delete[] (_str-4);
}
_str = str._str;
++*(int *)(str._str-4);
}
return *this;
}
private:
char *_str;
};
int main()
{
String str1("zhang");
String str2(str1);
str1.operator [](3);
/*String str2;
str2 = str1;
String str3("ccccc");
String str4;
str4 = str3;*/
//str3 = str1;
return 0;
}