方案四
class String { private: char* _str; };
方案四與方案三類似。方案四把用來計數的整形變量放在所開闢的內存空間的首部,
用*((int*)_str)就能來改變計數值
class String { public: String(char * str = "" ) //不能strlen(NULL) { _str = new char[strlen( str) + 5]; _str += 4; strcpy(_str, str); GetRefCount(_str) = 1; } String(const String &s) { _str = s._str; ++GetRefCount(_str); } //要考慮是s1=s2時,s1原先不爲空的情況,要先釋放原內存 //如果要釋放原內存時,要考慮它的_refCount減1後是否爲0, //爲零再釋放,否則其它對象指針無法再訪問這片空間 String& operator=(String& s) { if (this != &s ) { if (GetRefCount(_str ) == 1) { delete (_str-4); _str = s._str; ++GetRefCount(_str ); } else { --GetRefCount(_str ); _str = s._str; ++GetRefCount(_str ); } } return *this ; } //如果修改了字符串的內容,那所有指向這塊內存的對象指針的內容間接被改變 //如果還有其它指針指向這塊內存,我們可以從堆上重新開闢一塊內存空間, //把原字符串拷貝過來. //再去改變它的內容,就不會產生鏈式反應 char& String ::operator[](const size_t index ) //深拷貝 { if (GetRefCount(_str) == 1) { return _str[index ]; } else { // 1.減引用計數 --GetRefCount(_str ); // 2.拷貝 3.創建新的引用計數 char* tmp = new char [strlen(_str) + 5]; *((int *)tmp) = 1; tmp += 4; strcpy(tmp, _str); _str = tmp; return _str[index ]; } } int& GetRefCount(char* ptr) //獲取引用計數(隱式內聯函數) { return *((int *)(ptr -4)); } ~String() { if (--GetRefCount(_str) == 0) { cout << "~String" << endl; delete[] (_str-4); } } private: char* _str; };
以下是其它方案鏈接地址:
方案一:
http://iynu17.blog.51cto.com/10734157/1755179
方案二:
http://iynu17.blog.51cto.com/10734157/1755185
方案三:
http://iynu17.blog.51cto.com/10734157/1755208