浅拷贝
简单的来说就是,在有指针的情况下,浅拷贝只是增加了一个指针指向已经存在的内存,而深拷贝就是增加一个指针并且申请一个新的内存,使这个增加的指针指向这个新的内存。
举个例子:
#include<iostream>
using namespace std;
#include<string.h>
class String
{
public:
String(char *str="")
{
_str = str;
}
~String()
{
;
}
//s1=s2->s1.operator=(&s1,s2)
String& operator=(const String& s)
{
_str = s._str;
return *this;
}
char *GetStr()
{
return _str;
}
private:
char *_str;
};
void TestString()
{
String s1("hello world");
String s2;
s1 = s2;
cout << s1.GetStr() << endl;
cout << s2.GetStr() << endl;
}
测试部分
int main()
{
TestString();
system("pause");
}
上面的 =重载其是就是实现了浅拷贝。
原因:
1.由于对象之中含有指针数据类型.s1,s2恰好指向同一各内存,所以是浅拷贝。出了作用域,析构函数先清理对象s2,在清理对象s1,清理的是同一块空间,所以会崩溃。(一块空间只能被释放一次)
2.如果修改s3或者s1指向的内容,那么另一个指向的内容也会被修改。
深拷贝
采用深拷贝的情况下,释放内存的时候就不会出现在浅拷贝时重复释放同一内存的错误!
举个例子
1.传统写法
老老实实开空间,然后拷贝数据
#include<iostream>
using namespace std;
#include<string.h>
class String
{
public:
String(char *str = "")
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}
//s3(s1)
String(const String& s)
{
_str = new char[strlen(s._str) + 1];
strcpy(_str, s._str);
}
~String()
{
if (_str)
{
delete[] _str;
}
}
//s1=s2->s1.operator=(&s1,s2)
String& operator=(const String& s)
{
if (this != &s)
{
delete[] _str;
_str = new char[strlen(s._str) + 1];
strcpy(_str, s._str);
}
return *this;
}
char *GetStr()
{
return _str;
}
private:
char *_str;
};
void TestString()
{
String s1("hello world");
String s2("change world");
//String s3(s1);
//cout << s3.GetStr() << endl;
//s1 = s2;
//cout << s1.GetStr() << endl;
//cout << s2.GetStr() << endl;
s1 = s1;
cout << s1.GetStr() << endl;
cout << s2.GetStr() << endl;
}
测试部分
int main()
{
TestString();
system("pause");
}
2.现代写法
让别人拷贝好以后,再换过来
#include<iostream>
using namespace std;
#include<string.h>
class String
{
public:
String(char *str = "")
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}
//s3(s1)
String(const String& s)
:_str(NULL)
//tmp创建了和s1一样的空间,一样的内容。tmp和s3交换以后,s3指向了tmp指向的内容。而tmp指向的原本s3指向的内容也就是随机值。出了该作用域以后,析构函数进行清理工作,tmp的str进行释放,此处是对随机值进行释放(也就是释放野指针,所以会崩溃。因此我们在这里给s3的str赋值成NULL)
{
String tmp(s._str);
swap(_str, tmp._str);
}
s3(s1)
//String( String s)
//{
// swap(_str, s._str);
//}
~String()
{
if (_str)
{
delete[] _str;
}
}
//s1=s2->s1.operator=(&s1,s2)
String& operator=(const String& s)
{
if (this != &s)
{
String tmp(s._str);
swap(_str, tmp._str);
}
return *this;
}
s1=s2->s1.operator=(&s1,s2)
//String& operator=(const String& s)
//{
// if (this != &s)
// {
// delete[] _str;
// _str = new char[strlen(s._str) + 1];
// strcpy(_str, s._str);
// }
// return *this;
//}
char *GetStr()
{
return _str;
}
private:
char *_str;
};
void TestString()
{
String s1("hello world");
String s2("change world");
//String s3(s1);
//cout << s3.GetStr() << endl;
//s1 = s2;
//cout << s1.GetStr() << endl;
//cout << s2.GetStr() << endl;
s1 = s1;
cout << s1.GetStr() << endl;
cout << s2.GetStr() << endl;
}
测试部分:
int main()
{
TestString();
system("pause");
}