一、寫時拷貝的引入
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<這個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"< void test() { String str1("abcde"); String str2(str1); String str3; str3 = str2; cout<實現二:
將_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< void test1() { String str1("abcde"); String str2(str1); String str3; str3 = str2; cout<