1 浅拷贝
简单的赋值拷贝操作
2 深拷贝
在堆区重新申请空间,进行拷贝操作
3 对比:是否delete堆区的数据
栈区的数据在使用完毕后由编译器自动释放对应的内存;堆区的数据由程序员自己开辟,自己释放,即在使用完毕后不会自动释放。如果忘记对堆区的数据释放,会造成内存泄漏,直到整个程序执行完毕后,堆区的数据才被回收。
分别在栈区开辟一块内存,存放变量a;在堆区开辟一块内存,存放成员变量b。
错误示范:没有手动释放堆区的数据
#include<iostream>
using namespace std;
int *g_a;
int *g_b;
void test()
{
int a = 10;
int *b = new int(20);
cout << "a = " << a << endl;
cout << "b = " << *b << endl;
g_a = &a;
g_b = b;
cout << "test函数执行完毕!" << endl;
}
int main()
{
test();
cout << "a = " << *g_a << endl;
cout << "a = " << *g_a << endl;
cout << "a = " << *g_a << endl;
cout << "b = " << *g_b << endl;
cout << "b = " << *g_b << endl;
cout << "b = " << *g_b << endl;
return 0;
}
输出结果:
a = 10
b = 20
test函数执行完毕!
a = -858993460
a = -858993460
a = -858993460
b = 20
b = 20
b = 20
正确示范:堆区的数据使用完毕后,执行delete操作
#include<iostream>
using namespace std;
int *g_a;
int *g_b;
void test()
{
int a = 10;
int *b = new int(20);
cout << "a = " << a << endl;
cout << "b = " << *b << endl;
g_a = &a;
g_b = b;
delete b;
cout << "test函数执行完毕!" << endl;
}
int main()
{
test();
cout << "a = " << *g_a << endl;
cout << "a = " << *g_a << endl;
cout << "a = " << *g_a << endl;
cout << "b = " << *g_b << endl;
cout << "b = " << *g_b << endl;
cout << "b = " << *g_b << endl;
return 0;
}
输出结果:
a = 10
b = 20
test函数执行完毕!
a = -858993460
a = -858993460
a = -858993460
b = -572662307
b = -572662307
b = -572662307
4 浅拷贝与深拷贝
4.1 浅拷贝造成的错误
代码:
#include <iostream>
using namespace std;
class Person
{
public:
Person(int age,int height)
{
m_age = age;
m_height = new int (height);
cout << "Person 有参构造函数调用" << endl;
}
Person(const Person& p)
{
m_age = p.m_age;
m_height = p.m_height;
cout << "Person 默认拷贝构造函数调用" << endl;
}
~Person()
{
if (m_height != NULL)
{
delete m_height;
m_height = NULL;
}
cout << "Person 析构函数调用" << endl;
}
int m_age;
int *m_height;
};
void test()
{
Person p1(18, 180);
Person p2(p1);
cout << "p1的年龄: " << p1.m_age << " 身高: " << *p1.m_height << endl;
cout << "p2的年龄: " << p2.m_age << " 身高: " << *p2.m_height << endl;
}
int main()
{
test();
return 0;
}
输出结果:
Person 有参构造函数调用
Person 拷贝构造函数调用
p1的年龄: 18 身高: 180
p2的年龄: 18 身高: 180
Person 析构函数调用
运行中断,报错如下。 这就是浅拷贝带来的问题!
4.2 如果类成员有在堆区开辟的,一定要自己提供拷贝构造函数(深拷贝),防止浅拷贝带来的问题
代码:
#include <iostream>
using namespace std;
class Person
{
public:
Person(int age,int height)
{
m_age = age;
m_height = new int (height);
cout << "Person 有参构造函数调用" << endl;
}
Person(const Person& p)
{
m_age = p.m_age;
m_height = new int(*p.m_height);
cout << "Person (自定义)拷贝构造函数调用" << endl;
}
~Person()
{
if (m_height != NULL)
{
delete m_height;
m_height = NULL;
}
cout << "Person 析构函数调用" << endl;
}
int m_age;
int *m_height;
};
void test()
{
Person p1(18, 180);
Person p2(p1);
cout << "p1的年龄: " << p1.m_age << " 身高: " << *p1.m_height << endl;
cout << "p2的年龄: " << p2.m_age << " 身高: " << *p2.m_height << endl;
}
int main()
{
test();
return 0;
}
输出结果:
Person 有参构造函数调用
Person (自定义)拷贝构造函数调用
p1的年龄: 18 身高: 180
p2的年龄: 18 身高: 180
Person 析构函数调用
Person 析构函数调用
4.3 浅拷贝与深拷贝图解
浅拷贝,只是将地址复制,拷贝前后两份地址指向同一块内存,p1调用析构函数,会立马释放该内存空间;当p2调用析构函数时,没有内存可以释放,故发生错误。 深拷贝,在堆区开辟一块内存,存放拷贝后的数据,这样,p1、p2调用析构函数时就不会互相干扰。
如果还是不明白,请参考https://www.bilibili.com/video/BV1et411b73Z?p=110
|