c++中的深浅拷贝

xiaoxiao2021-02-28  33

**一、浅拷贝:**

1)代码: 1、构造:

String ::String(const char* str="") :_str(new char[strlen(str)+1]) { strcpy(_str, str); }

2、拷贝构造

String::String(const String&s) : _str(s._str) {}

3、赋值浅拷贝

//s2==s1 String& String:: operator=(const String&s) { if (this!=&s) { _str = s._str; } return *this; }

2)图解:

4、析构

String::~String() { if (_str) { delete[] _str; } }

由于浅拷贝会引发析构两次的问题 所以引入了引用计数,为了保证证每个对象的独立性,所以引入了写时拷贝,可以理解为引用计数和写时拷贝就是浅拷贝的一种优化。 二、引用计数与写时拷贝: 1)代码: 1、构造:

String::String(const char* str = "")//拷贝 :_str(new char[strlen(str)+1]) ,_pCount(new int(1))//开辟1块空间并初始化为1 { strcpy(_str, str); }

2、拷贝构造:

String::String(const String&s)//拷贝构造 :_str(s._str) ,_pCount(s._pCount) { (*_pCount)++; }

调试结果:

图解: 问题:一个改了会影响另一个

String s1("hello world"); String s2(s1); s1[2] = 'x'; cout << s1.c_str() << endl; cout << s2.c_str() << endl;

调试结果:

3、赋值运算符重载:

//s2=s1 String& String:: operator=(const String&s)//赋值运算符重载 { if (this != &s) { if (--(*_pCount) == 0)//这里不调用析构函数, //因为析构函数一般都是在出了函数作用域才被调用 { delete[] _str; delete _pCount; } _str = s._str; _pCount = s._pCount; ++(*_pCount); } return *this; } String s1("hello world"); String s2(s1); s1[2] = 'x'; cout << s1.c_str() << endl; cout << s2.c_str() << endl;

调试结果:

图解:

4、写时拷贝(下开法):

void String::CopyOnWrite() { if ((*_pCount) > 1) { char*newstr = new char[strlen(_str) + 1]; strcpy(newstr, _str); _str = newstr; --(*_pCount); _pCount = new int(1); } } char& String::operator[](size_t pos)//可以修改字符串中的字符 { CopyOnWrite(); return _str[pos]; }

为了解决两个程序会相互影响 调试结果: 图解:

5、析构:

String::~String() { if (--(*_pCount)==0) { delete[] _str; delete _pCount; _str = NULL; _pCount = NULL; } }

三、深拷贝(传统写法和现代写法) 传统写法:

String::String(const char*str = "") :_str(new char[strlen(str) + 1]) { strcpy(_str, str); } //s2(s1) String::String(const String& s) : _str(new char[strlen(s._str)+1]) { strcpy(_str, s._str); } //s3=s1 String& String::operator=(const String&s) { if (this!=&s) { char*str = new char[strlen(_str) + 1]; delete[] _str; _str = str; strcpy(_str, s._str); } return *this; } String::~String() { if (_str) { delete[] _str; } }

调试结果: 图解: 现代写法:

String::String(const char*str = "") :_str(new char[strlen(str) + 1]) { strcpy(_str, str); } //s2(s1) String::String(const String& s) : _str(NULL) { String tmp(s._str); swap(tmp._str, _str); } //s1=s3 String& String::operator=(const String&s) { if (this != &s) { String tmp(s._str); swap(_str, tmp._str); } return *this; } String::~String() { if (_str) { delete[] _str; } }

调试结果: 图解: 补充写时拷贝(头开法):

String::String(const char* str = "") :_str(new char[strlen(str)+5]) { _str += 4; strcpy(_str, str); *((int*)(_str-4)) = 1; } //s2(s1) String::String(const String& s) :_str(s._str) { *((int*)(_str-4)) += 1; } //s1=s2 String& String ::operator=(const String& s) { if (this!=&s) { if (--(*(int*)(_str - 4)) == 0) { delete[](_str - 4); } _str = s._str; ++(*(int*)(_str - 4)); } return *this; } void String::CopyOnWrite() { if ((*(int*)(_str-4))>1) { char* newstr = new char[strlen(_str) + 5]; strcpy(newstr, _str); --(*(int*)(_str - 4)); _str = newstr; ++(*(int*)(_str - 4)); } } char &String::operator[](size_t pos) { CopyOnWrite(); return _str[pos]; } String::~String() { if (--(*(int*)(_str-4))==0) { delete[] (_str-4); } }

引用计数导致的改一块两块一块改的问题 写时拷贝: 调试结果: 图解:

转载请注明原文地址: https://www.6miu.com/read-2619615.html

最新回复(0)