1. 写时才拷贝(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;

}