赞
踩
浅拷贝:只是直接将s1的值拷贝过来,s1、s2共用同一块内存。
缺陷是调用析构函数时一块内存会被多次释放,导致程序崩溃。
class String { public: String(const char* str) :_str(new char[strlen(str) + 1]) { strcpy(_str, str); } String(const String& s) :_str(s._str) {} String& operator=(const String& s) { if (this != &s) { _str = s._str; } return *this; } ~String() { if (_str) { cout << "delete" << endl; delete[] _str; } } private: char* _str; }; void TestString() { String s1("bigbang"); String s2(s1); String s3("12345"); s3 = s1; } int main() { TestString(); system("pause"); return 0; }
深拷贝:在拷贝构造时开辟了空间,s1、s2各占有一块内存,无论析构多少次程序都不会崩溃。
//深拷贝传统写法 class String { public: String(char* str = "") :_str(new char[strlen(str) + 1]) { strcpy(_str, str); } String(const String& s) :_str(new char[strlen(s._str) + 1]) { strcpy(_str, s._str); } //String& operator=(const String& s) //缺陷:new开辟空间可能会失败,s1将会被破坏 //{ // if (this != &s) // { // delete[] _str; // _str = new char[strlen(s._str) + 1]; // strcpy(_str, s._str); // } // return *this; //} String& operator=(const String& s) //解决了上述缺陷 { if (this != &s) { char* tmp = new char[strlen(s._str) + 1]; strcpy(tmp, s._str); delete[] _str; _str = tmp; } return *this; } ~String() { if (_str) { cout << "delete" << endl; delete[] _str; _str = NULL; } } private: char* _str; }; void TestString() { String s1("bigbang"); String s2(s1); } int main() { TestString(); system("pause"); return 0; }
//深拷贝现代写法:只在构造函数中new,只在析构函数中delete,可维护性变强 class String { public: String(char* str = "") :_str(new char[strlen(str) + 1]) { strcpy(_str, str); } String(const String& s) :_str(NULL) { String tmp(s._str); //调用构造函数开辟临时空间,交换后可把原来的空间释放掉 swap(_str, tmp._str); } String& operator=(const String& s) { if (_str != s._str) { String tmp(s); swap(_str, tmp._str); } return *this; } //String& operator=(String s) //针对已经存在的两个对象 //{ // swap(_str, s._str); // return *this; //} ~String() { if (_str) { cout << "delete" << endl; delete[] _str; _str = NULL; } } private: char* _str; }; void TestString() { String s1("bigbang"); String s2(s1); String s3; s3 = s1; } int main() { TestString(); system("pause"); return 0; }
在引用计数中,每一个对象负责维护对象所有引用的计数值。当一个新的引用指向对象时,引用计数器就递增,当去掉一个引用时,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。
class String { public: String(char* str = "") :_str(new char[strlen(str) + 1]) , _refCount(new int(1)) { strcpy(_str, str); } String(const String& s) :_str(s._str) , _refCount(s._refCount) { ++(*_refCount); } String& operator=(const String& s) { // 1.s1和s2是否指向同一块空间 // 2.减减s1指向空间的引用计数,如s1是最后一块管理对象,则释放 if (_str != s._str) { this->Release(); _str = s._str; _refCount = s._refCount; ++(*_refCount); } return *this; } String& operator=(String s) //s是临时开辟出来的一块空间,出了函数会自动释放 { swap(_str, s._str); swap(_refCount, s._refCount); //交换后引用计数不改变 return *this; } ~String() { Release(); } void Release() { if (--(*_refCount) == 0) { cout << "delete" << endl; delete[] _str; delete _refCount; //注意delete的格式和new的格式对齐 } } private: char* _str; int* _refCount; }; void TestString() { String s1("bigbang"); String s2(s1); String s3; s3 = s1; } int main() { TestString(); system("pause"); return 0; }
//引用计数的浅拷贝--现代写法+写时拷贝:指用浅拷贝的方法拷贝其他对象,多个指针指向同一块空间, //只有当对其中一个对象修改时,才会开辟一个新的空间给这个对象,和它原来指向同一空间的对象不会受到影响。 class String { public: String(char* str = "") :_str(new char[strlen(str) + 1]) , _refCount(new int(1)) { strcpy(_str, str); } String(const String& s) :_str(s._str) , _refCount(s._refCount) { ++(*_refCount); } String& operator=(const String& s) { if (_str != s._str) { this->Release(); _str = s._str; _refCount = s._refCount; ++(*_refCount); } return *this; } String& operator=(String s) { swap(_str, s._str); swap(_refCount, s._refCount); return *this; } void Release() { if (--(*_refCount) == 0) { cout << "delete" << endl; delete[] _str; delete _refCount; } } ~String() { Release(); } char& operator[](size_t index) { CopyOnWrite(); assert(index < strlen(_str)); return _str[index]; } const char& operator[](size_t index) const { assert(index < strlen(_str)); return _str[index]; } void CopyOnWrite() { if (*_refCount > 1) { char* tmp = new char[strlen(_str) + 1]; strcpy(tmp, _str); --(*_refCount); _refCount = new int(1); _str = tmp; } } private: char* _str; int* _refCount; }; void Fun(const String& s) { cout << s[4] << endl; } void TestString() { String s1("bigbeng"); String s2(s1); String s3 = s2; Fun(s1); s1[4] = 'a'; cout << s1[4] << endl; } int main() { TestString(); system("pause"); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。