实现CMyString类,实现赋值运算符函数(深拷贝与浅拷贝(写时拷贝))
深拷贝:赋值运算符函数说明
步骤1、释放原来的内存空间
步骤2、再重新开辟要赋值的对象的大小的空间
步骤3、再将另一个对象的值拷贝给this对象
友元函数的说明:由于输出重载需要俩个参数,不能再隐含this指针,故使用友元函数
代码如下:
<span style="font-size:18px;">class CMyString { public: CMyString() :str(new char[1]) { str[0] = '\0'; } CMyString(char* _str) :str(new char[strlen(_str)+1]) { strcpy(str, _str); } CMyString(CMyString& s) :str(NULL) { delete[] str; str = new char[strlen(s.str) + 1]; strcpy(str, s.str); } CMyString& operator=(CMyString& s) { if (this != &s) { delete[] str; str = new char[strlen(s.str) + 1]; strcpy(str, s.str); } return *this; } ~CMyString() { if (str) { delete[] str; str = NULL; } } friend ostream& operator<<(ostream& os,CMyString& s) { os << s.str; return os; } private: char* str; };</span>
浅拷贝:赋值运算符函数说明
步骤1、Release();
步骤2、将this->str 指向 s.str;
步骤3、++GetCount(str);
GetCount()函数说明:得到当前对象的引用计数--->*(int*)(str-4);
减4是因为对象在创建的时候除了多开辟了一个字节给‘|0’,还多给引用计数开辟了4个字节,且将str指向了引用计数的后4个字节(即字符串处),要得到引用计数需减4,如下图1:
Release()函数说明:判断str是否为空且引用计数减1之后是否为0;如果减1之后为0,说明后期无对象再去使用这块内存,则将其释放掉,反之不去释放;
写时拷贝char& operator[](size_t index);函数说明:
步骤1、减去引用计数
步骤2、拷贝
步骤3、创建引用计数
代码如下:
<span style="font-size:18px;">class CMyString { private: void Release() { if (str && --GetCount(str) == 0) { delete[](str - 4); str = NULL; } } int& GetCount(char* str) { return (*(int*)(str - 4)); } public: CMyString(char* _str = "") :str(new char[strlen(_str) + 5]) { *(int*)str = 1; str += 4; strcpy(str, _str); } CMyString(const CMyString& s) :str(s.str) { ++GetCount(str); } CMyString& operator=(const CMyString& s) { if (this != &s) { Release(); str = s.str; ++GetCount(str); } return *this; } //写时拷贝 char& operator[](size_t index) { if (GetCount(str) > 1) { --GetCount(str); char* tmp = new char[strlen(str) + 5]; tmp += 4; GetCount(tmp) = 1; strcpy(tmp, str); str = tmp; } return str[index]; } ~CMyString() { Release(); } friend ostream& operator<<(ostream& os, CMyString& s) { os << s.str; return os; } private: char* str; };</span>
int main() { CMyString s1("hello"); CMyString s2; s2 = s1; CMyString s3 = s1; cout << s1 << endl; cout << s2 << endl; cout << s3 << endl; //浅拷贝中的写时拷贝测试用例 s3[0] = 'b'; s3[1] = 'l'; s3[2] = 'k'; cout << s3 << endl; return 0; }
图1:
图2: