String类的三种实现
- 浅拷贝
1 class String 2 { 3 public: 4 String(const char* pdata)//构造函数 5 :_pdata(new char[strlen(pdata) + 1]) 6 { 7 strcpy(_pdata, pdata); 8 } 9 String(const String&s)//拷贝构造 10 :_pdata(s._pdata) 11 {} 12 ~String()//析构函数 13 { 14 if (NULL != _pdata) 15 { 16 delete[]_pdata; 17 _pdata = NULL; 18 } 19 } 20 String &operator=(const String&s) 21 { 22 //检查自赋值 23 if (this != &s) 24 { 25 char*temp = new char[strlen(s._pdata) + 1]; 26 strcpy(temp, s._pdata); 27 delete[]_pdata; 28 _pdata = temp; 29 } 30 return *this; 31 } 32 private: 33 char*_pdata; 34 }; 35 void main() 36 { 37 String s1 ("hello world"); 38 String s2=s1; 39 }
当类里面有指针对象时,进行简单赋值的浅拷贝,两个对象指向同一块内存,存在崩溃的问题!这里我们要进行深拷贝。
- 深拷贝
1 # define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 #include<string> 4 using namespace std; 5 class String 6 { 7 public: 8 String(const char* pdata)//构造函数 9 :_pdata(new char[strlen(pdata) + 1]) 10 { 11 strcpy(_pdata, pdata); 12 } 13 String(const String&s)//拷贝构造 14 :_pdata(new char[strlen(s._pdata) + 1]) 15 { 16 strcpy(_pdata, s._pdata); 17 } 18 ~String()//析构函数 19 { 20 if (NULL != _pdata) 21 { 22 delete[]_pdata; 23 _pdata = NULL; 24 } 25 } 26 String &operator=(const String&s) 27 { 28 //检查自赋值 29 if (this != &s) 30 { 31 char*temp = new char[strlen(s._pdata) + 1]; 32 strcpy(temp, s._pdata); 33 delete[]_pdata; 34 _pdata = temp; 35 } 36 return *this; 37 } 38 private: 39 char*_pdata; 40 }; 41 //简洁版 42 class String 43 { 44 public: 45 String(const char* pData) 46 : _pData(new char[strlen(pData) + 1]) 47 { 48 strcpy(_pData, pData); 49 } 50 51 String(const String& s) 52 : _pData(NULL) 53 { 54 String temp(s._pData); 55 std::swap(_pData, temp._pData); 56 } 57 58 String& operator=(const String& s) 59 { 60 if (this != &s) 61 { 62 String temp(s._pData); 63 std::swap(_pData, temp._pData); 64 } 65 return *this; 66 } 67 ~String() 68 { 69 if (NULL != _pData) 70 { 71 delete[] _pData; 72 _pData = NULL; 73 } 74 } 75 private: 76 char* _pData; 77 }; 78 void main() 79 { 80 String s1 ("hello world"); 81 String s2=s1; 82 }
- 写时拷贝
1 #include<iostream> 2 #include<string.h> 3 #include<assert.h> 4 namespace COW 5 { 6 class String 7 { 8 public: 9 String(const char* pData) 10 : _pData(new char[strlen(pData) + 1]) 11 , _refCount(new int) 12 { 13 *_refCount = 1; 14 strcpy(_pData, pData); 15 } 16 17 // String s2(s1); 18 String(String& s) 19 : _pData(s._pData) 20 , _refCount(s._refCount) 21 { 22 ++(*_refCount); 23 } 24 25 // s1 = s2; 26 String& operator=(String s) 27 { 28 if (this != &s) 29 { 30 if (--(*_refCount) == 0) 31 { 32 delete[] _pData; 33 delete _refCount; 34 } 35 36 _pData = s._pData; 37 _refCount = s._refCount; 38 ++(*_refCount); 39 } 40 41 return *this; 42 } 43 44 ~String() 45 { 46 if (--(*_refCount) == 0) 47 { 48 delete[] _pData; 49 delete _refCount; 50 } 51 } 52 // 返回值 函数名(参数) 53 char& operator[](int index) 54 { 55 // 检测返回 56 // *_refCount > 1 57 // *_refCount = 1 58 if (*_refCount > 1) 59 { 60 (*_refCount)--; 61 String temp(_pData); 62 _pData = temp._pData; 63 _refCount = temp._refCount; 64 (*_refCount)++; 65 } 66 return _pData[index]; 67 } 68 /*const char& operator[](int index)const 69 { 70 71 return _pData[index]; 72 }*/ 73 private: 74 char* _pData; 75 int* _refCount; 76 }; 77 } 78 void FunTest() 79 { 80 COW::String s1("12345"); 81 COW::String s2("123456789"); 82 const COW::String s3 = s2; 83 s1 = s2; 84 s2[0] = '6'; 85 //std::cout << s3[1]; 86 } 87 int main() 88 { 89 FunTest(); 90 return 0; 91 }
string 之间拷贝时不是深拷贝,只拷贝了指针, 也就是共享同一个字符串内容, 只有在内容被修改的时候, 才真正分配了新的内存并 copy 。 比如 s[0]='1' 之类的修改字符串内容的一些write操作, 就会申请新的内容,和之前的共享内存独立开。 所以称之为 『copy-on-write』