浅拷贝
拷贝就是复制,就相当于把一个对象中的所有的内容,复制一份给另一个对象,直接复制,也就是把一个对象的地址给了另一个对象,他们指向相同,两个对象之间有共同的属性或者方法,都可以使用,但是在对象释放的时候会调用两次析构函数,从而造成指针悬挂现象,造成程序崩溃。
深拷贝
深拷贝是指,既会拷贝基本数据类型的值,也会针对实例对象的引用地址所指向的对象进行复制,即程序会在堆内存申请空间来存储数据,解决了数据悬挂问题。
例如:赋值造成的浅拷贝
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(int age, int height)
{
m_Age = age;
m_Height = new int(height);
}
~Person()
{
if (m_Height != NULL)
{
delete m_Height;
m_Height = NULL;
}
}
Person& operator=(const Person&);
//当我们不提供拷贝构造函数时,系统默认为浅拷贝,代码类似以下
//Person(const Person &p)
//{
// m_Age = p.m_Age;
// m_Height = p.m_Height;
// //深拷贝
// m_Height = new int(*p.m_Height);
//}
int m_Age;
int* m_Height;
};
int main()
{
Person p1(18, 180);
cout << "p1的年龄为:" << p1.m_Age << " 身高为:" << *p1.m_Height << endl;
//Person p2(p1);
//cout << "p2的年龄为:" << p2.m_Age << " 身高为:" << *p2.m_Height << endl;
Person p3(20, 190);
p3 = p1;
cout << "p3的年龄为:" << p3.m_Age << " 身高为:" << *p3.m_Height << endl;
system("pause");
return 0;
}
Person& Person::operator=(const Person& p)
{
if (this == &p)
return *this;
delete m_Height;
m_Height = new int(*p.m_Height);
return *this;
}
这里程序崩溃,因为浅拷贝造成s2析构后,s1成为野指针,s1继续析构重复释放同一块内存,造成内存泄漏。
我们在VS中确实也看到了两个内存相同
此时需要用深拷贝来解决
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(int age, int height)
{
m_Age = age;
m_Height = new int(height);
}
~Person()
{
if (m_Height != NULL)
{
delete m_Height;
m_Height = NULL;
}
}
Person& operator=(const Person&);
//当我们不提供拷贝构造函数时,系统默认为浅拷贝,代码类似以下
//Person(const Person &p)
//{
// m_Age = p.m_Age;
// m_Height = p.m_Height;
// //深拷贝
// m_Height = new int(*p.m_Height);
//}
int m_Age;
int* m_Height;
};
int main()
{
Person p1(18, 180);
cout << "p1的年龄为:" << p1.m_Age << " 身高为:" << *p1.m_Height << endl;
//Person p2(p1);
//cout << "p2的年龄为:" << p2.m_Age << " 身高为:" << *p2.m_Height << endl;
Person p3(20, 190);
p3 = p1;
cout << "p3的年龄为:" << p3.m_Age << " 身高为:" << *p3.m_Height << endl;
system("pause");
return 0;
}
Person& Person::operator=(const Person& p)
{
if (this == &p)
return *this;
delete m_Height;
m_Height = new int(*p.m_Height);
return *this;
}
重载赋值号,赋值时申请一块新的空间存储数据。
系统的拷贝构造函数带来的浅拷贝
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(int age, int height)
{
m_Age = age;
m_Height = new int(height);
}
~Person()
{
if (m_Height != NULL)
{
delete m_Height;
m_Height = NULL;
}
}
//当我们不提供拷贝构造函数时,系统默认为浅拷贝,代码类似以下
Person(const Person &p)
{
m_Age = p.m_Age;
m_Height = p.m_Height;
//深拷贝
//m_Height = new int(*p.m_Height);
}
int m_Age;
int* m_Height;
};
int main()
{
Person p1(18, 180);
cout << "p1的年龄为:" << p1.m_Age << " 身高为:" << *p1.m_Height << endl;
Person p2(p1);
cout << "p2的年龄为:" << p2.m_Age << " 身高为:" << *p2.m_Height << endl;
system("pause");
return 0;
}
当我们没有自己写拷贝构造函数时,系统给我们提供了拷贝构造函数,但显然系统崩了,还是一个浅拷贝,所以我们需要自己写一个拷贝构造函数解决,
总结:深拷贝和浅拷贝的区别是在对象状态中包含其它对象的引用的时候,当拷贝一个对象时,如果需要拷贝这个对象引用的对象,则是深拷贝,否则是浅拷贝。