String —— 深浅拷贝
浅拷贝就是由默认的拷贝构造函数和赋值运算符重载所实现的数据成员逐一赋值。通常默认的函数是能够胜任此工作的,但若类中含有指针类型的数据,这种按数据成员逐一赋值的方法将会产生错误。为了解决浅拷贝出现的错误,必须显示地定义一个自己的拷贝构造函数,使其不但复制数据成员,而且为对象分配各自的内存空间,这就是所谓的深拷贝。
1、原有的内存没有释放,造成内存泄漏
2、两个指向同一块内存,任何一方变动都会影响另一方
3、对同一块空间析构两次
这时就需要自己写拷贝构造、赋值运算符重载,有两种写法。传统写法和现代写法。
传统写法 —— 自己开空间,自己拷贝
现代写法 —— 剥削
//传统写法
class String
{
public:
String(const char* str = "") //全缺省带参的构造函数
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}
//s3(s2)
//s4(s1)
String(const String& s) //拷贝构造
:_str(new char[strlen(s._str) + 1])
{
strcpy(_str, s._str);
}
//s1 = s2
//s1 = s1
String& operator=(const String& s)
{
if (this != &s)
{
char* str = new char[strlen(s._str) + 1];
delete[] _str;
_str = str;
strcpy(_str, s._str);
}
return *this;
}
~String()
{
if (_str)
{
delete[] _str;
}
}
const char* c_str()
{
return _str;
}
private:
char* _str;
};
//现代写法
class String
{
public:
String(const char* str = "") //全缺省带参的构造函数
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}
//String s2(s1)
String(const String& s) //拷贝构造
:_str(NULL)
{
String tmp(s._str);
swap(_str, tmp._str);
}
s1 = s2
//String& operator=(const String& s)
//{
// if (this != &s)
// {
// String tmp(s._str);
// swap(tmp._str, _str);
// }
// return *this;
//}
String& operator=(String s) //借助形参对象
{
swap(s._str, _str);
return *this;
}
~String()
{
if (_str)
{
delete[] _str;
}
}
const char* c_str()
{
return _str;
}
private:
char* _str;
};