引用计数的浅拷贝的两种实现方式
方法一:String类中采用char* _str和int* _pRefCount;但利用指针_pRefCount重新开辟空间存放引用计数,会产生大量内存碎片。
代码如下:
#include<iostream> using namespace std; #include<assert.h> class String { public: String(char* str="") :_str(new char[strlen(str)+1]) ,_pRefCount(new int[1]) { strcpy(_str, str); *_pRefCount = 1; } String(const String& s) :_str(s._str) ,_pRefCount(s._pRefCount) { ++(*_pRefCount); } //运算符重载 String& operator=(const String& s) { if (--(*_pRefCount) == 0) { delete[] _str; delete _pRefCount; } _str = s._str; _pRefCount = s._pRefCount; ++(*_pRefCount); return *this; } ~String() { if (--(*_pRefCount) == 0) { cout << "~String()" << endl; delete[] _str; delete _pRefCount; } } int _GetRefCount() { return *_pRefCount; } void put() { cout << _str << endl; } private: char* _str; int* _pRefCount; }; void Test() { String S; String s1("Luoluo"); String s2(s1); S.put(); s2 = s1; s2.put(); //监视查看或断言判断是否正确 assert(s1._GetRefCount() == 2); assert(s2._GetRefCount() == 2); String s3("Feifei"); String s4(s3); s3.put(); s3 = s1; s3.put(); assert(s1._GetRefCount() == 3); assert(s2._GetRefCount() == 3); assert(s3._GetRefCount() == 3); assert(s4._GetRefCount() == 1); } int main() { Test(); system("pause"); return 0; }
方法二:类中只采用_str一个变量,用开辟的前一块空间存放引用计数。利用强制转换前后偏移,获取引用计数以及存放字符串的位置。对于两个或多个相同的字符串,为了方便修改某字符串,并不影响其他字符串可以通过写实拷贝来实现。
代码如下:
#include<iostream> using namespace std; class String { public: String(char* str = "") :_str(new char[strlen(str)+5]) { _str += 4; _GetRefCount(_str) = 1; strcpy(_str, str); } String(const String& s) :_str(s._str) { ++_GetRefCount(_str); } String& operator=(const String& s) { if (_str != s._str) { _Release(); _str = s._str; ++_GetRefCount(_str); } return *this; } //写实拷贝-----写谁谁拷贝 char& operator[](size_t index) { if (_GetRefCount(_str) > 1) { char* tmp = new char[strlen(_str) + 5]; tmp += 4; _GetRefCount(tmp) = 1; strcpy(tmp, _str); --_GetRefCount(_str); _str = tmp; } return _str[index]; } ~String() { cout << "~String()" << endl; _Release(); } int& _GetRefCount(char* str) { return(*(int*)(str - 4)); } void _Release() { if (--(_GetRefCount(_str)) == 0) { delete[](_str - 4);//指针返回首地址位置,释放整段空间 } } void put() { cout << _GetRefCount(_str)<<"---------"<<_str << endl; } private: char* _str; }; void Test() { String S; String s1 = "abclefg"; String s2(s1); S.put(); s1.put(); s2.put(); s2 = s1; s2.put(); String s3 = "hijklmn"; String s4(s3); s3.put(); s3 = s1; s3.put(); s1[3] = 'd'; s1.put(); s2.put(); } int main() { Test(); system("pause"); return 0; }