深浅拷贝
class String
{
public:
String(const char *pStr = "")
{
if (pStr == NULL)
pStr = "";
_str = new char[strlen(pStr) + 1];
strcpy(_str, pStr);
}
~String()
{
if (_str)
delete[] _str;
}
private:
char *_str;
};
int main()
{
String str1("hello");
String str2(NULL);
String str3;
system("pause");
return 0;
}
浅拷贝:
也称位拷贝,编译器只是将对象中的值采用基本类型值复制的方式拷贝过来,如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放, 以为还有效,所以当继续对资源进行操作时,就会发生访问违规
当没有定义copy构造和copy assignment操作符将使用系统默认的copy构造和copy assignment操作符
String(const String& s)
:_str(s._str)
{}
String &operator=(const String& s)
{
_str = s._str;
return *this;
}
当类里面有指针对象时,拷贝构造和赋值运算符重载只进行值拷贝,两个对象共用同一块空间,对象销毁时程序会发生内存访问违规
void Test()
{
String s1("hello");
String s2(s1);
String s3("world");
s1 = s3;
}
深拷贝
解决方法:用户给出自己的copy构造和copy assignment操作符
String(const String& s)
:_str(new char[strlen(s._str) + 1])
{
strcpy(_str, s._str);
}
String &operator=(const String& s)
{
//不允许自己给自己赋值
if (this != &s)
{
delete[] _str;
_str = new char[strlen(s._str) + 1];
strcpy(_str, s._str);
}
return *this;
}
现代写法
//第一种写法,借助构造函数
String(const String& s)
:_str(NULL)//必须要注意初始化为空
{
String tmpstr(s._str);
swap(_str, tmpstr._str);
}
//第一种写法,借助构造函数
String &operator=(const String& s)
{
if (this != &s)
{
String tmpstr(s._str);
swap(_str, tmpstr._str);
}
return *this;
}
//第二种写法:借助拷贝构造函数
//必然会进行对象值拷贝操作(地址会变)
String &operator = (String s)//s已经是形参的临时变量
{
swap(_str, s._str);
return *this;
}