深拷贝与浅拷贝(3)
浅拷贝:简单的赋值拷贝操作,编译器提供的拷贝构造函数
深拷贝:在堆区重新申请空间,进行拷贝操作,程序员提供
浅拷贝:
如果利用编译器提供的拷贝构造函数,会做浅拷贝操作。
1 #include <iostream> 2 using namespace std; 3 4 class Person 5 { 6 public: 7 8 Person() 9 { 10 cout << "Person默认构造函数的调用" << endl; 11 } 12 13 Person(int age,int height) 14 { 15 m_Age = age; 16 m_Height = new int(height); //指针来接收 17 cout << "Person有参构造函数的调用" << endl; 18 } 19 20 ~Person() 21 { 22 //if (m_Height != NULL) 23 //{ 24 //delete m_Height; 25 //m_Height = NULL; 26 //} 27 cout << "Person析构函数的调用" << endl; 28 } 29 30 int m_Age; 31 int *m_Height; //堆区数据要用指针来接收 32 33 }; 34 35 void test_01() 36 { 37 Person p1(18, 160); 38 39 cout << "p1的年龄: " << p1.m_Age << " p1的身高: " << *p1.m_Height << endl; 40 41 Person p2(p1); 42 43 cout << "p2的年龄: " << p2.m_Age << " p2的身高: " << *p2.m_Height << endl; 44 } 45 46 int main(void) 47 { 48 test_01(); 49 50 system("pause"); 51 return 0; 52 }
堆区开辟的数据,由程序员手动开辟,也要由程序员手动释放。
什么时候释放呢?在对象被销毁之前释放,对象什么时候被销毁呢?程序执行结束之前。程序执行结束之前会调用什么函数呢?析构函数!
析构函数终于排上用场了~~~~
1 #include <iostream> 2 using namespace std; 3 4 class Person 5 { 6 public: 7 8 Person() 9 { 10 cout << "Person默认构造函数的调用" << endl; 11 } 12 13 Person(int age,int height) 14 { 15 m_Age = age; 16 m_Height = new int(height); 17 cout << "Person有参构造函数的调用" << endl; 18 } 19 20 ~Person() 21 { 22 if (m_Height != NULL) //释放 23 { 24 delete m_Height; 25 m_Height = NULL; 26 } 27 cout << "Person析构函数的调用" << endl; 28 } 29 30 int m_Age; 31 int *m_Height; 32 33 }; 34 35 void test_01() 36 { 37 Person p1(18, 160); 38 39 cout << "p1的年龄: " << p1.m_Age << " p1的身高: " << *p1.m_Height << endl; 40 41 Person p2(p1); 42 43 cout << "p2的年龄: " << p2.m_Age << " p2的身高: " << *p2.m_Height << endl; 44 } 45 46 int main(void) 47 { 48 test_01(); 49 50 system("pause"); 51 return 0; 52 }
运行上述代码,观察一下:
是什么原因造成的呢?我们来分析一下:
1 void test_01() 2 { 3 Person p1(18, 160); 4 5 cout << "p1的年龄: " << p1.m_Age << " p1的身高: " << *p1.m_Height << endl; 6 7 Person p2(p1); 8 9 cout << "p2的年龄: " << p2.m_Age << " p2的身高: " << *p2.m_Height << endl; 10 }
栈区的数据先进后出:编译器会先执行p2的析构函数,然后再执行p1的析构函数。换句话说:就是堆区的数据已经被p2的析构函数释放了,p1就没有权限
去访问了!
总结:如果使用浅拷贝的话,会造成堆区的数据重复释放,系统会报错。
深拷贝:
专门用来解决浅拷贝带来的问题。
思路:
自己写自己拷贝构造函数,在拷贝构造函数中重新为 m_Height 在堆区开辟一个空间,这样问题就解决了。
代码实现:
1 //拷贝构造函数 2 Person(const Person &p) 3 { 4 m_Age = p.m_Age; 5 //m_Height = p.m_Height;//编译器默认实现的就是这行代码,结果造成浅拷贝的问题 6 //深拷贝的操作 7 m_Height = new int(*p.m_Height); 8 9 cout << "Person拷贝构造函数的调用" << endl; 10 }
再次运行就没有问题了。