拷贝结构函数顾名思义就是复制对象。
先讲一下默认拷贝函数:
默认拷贝就是直接赋值,让程序调用默认拷贝结构函数。
Student p1; Student p2 = p1//或者Student p2(p1);
程序开始运行时,创建p1对象,p1对象的构造函数从堆中分配空间并赋给数据成员pName,执行,p2=p1时,因为没有定义拷贝构造函数,于是就调用默认拷贝构造函数,
使得p2与p1完全一样,并没有新分配堆空间给p2, p1与p2的pName都是同一个值。析构p2时,将堆中字符串清成空串,然后将堆空间返还给系统;
析构p1时,因为这是pName指向的是空串,所以第三行输出中显示的只是Destructing,当执行 delete pName ; 按道理系统应该报错,但在gcc中没有。
重点讲一下,深拷贝和浅拷贝。
这里借鉴一个前辈的例子:(前辈写的很好,大家可以看下)
https://www.cnblogs.com/raichen/p/4752025.html
#include <iostream> #include <cstring> class Person { public : // 构造函数 Person(char * pN) { cout << "一般构造函数被调用 !\n"; m_pName = new char[strlen(pN) + 1]; //在堆中开辟一个内存块存放pN所指的字符串 if(m_pName != NULL) { //如果m_pName不是空指针,则把形参指针pN所指的字符串复制给它 strcpy(m_pName ,pN); } } // 系统创建的默认复制构造函数,只做位模式拷贝 Person(Person & p) { //使两个字符串指针指向同一地址位置 m_pName = p.m_pName; } ~Person( ) { delete m_pName; } private : char * m_pName; }; void main( ) { Person man("lujun"); Person woman(man); // 结果导致 man 和 woman 的指针都指向了同一个地址 // 函数结束析构时 // 同一个地址被delete两次 } // 下面自己设计复制构造函数,实现“深拷贝”,即不让指针指向同一地址,而是重新申请一块内存给新的对象的指针数据成员 Person(Person & chs); { // 用运算符new为新对象的指针数据成员分配空间 m_pName=new char[strlen(p.m_pName)+ 1]; if(m_pName) { // 复制内容 strcpy(m_pName ,chs.m_pName); } // 则新创建的对象的m_pName与原对象chs的m_pName不再指向同一地址了 }
因为编译不同,可能不能通过编译,但这不是重点。
直接利用浅拷贝,m_pName = p.m_pName,后者复制给前者,但资源(堆空间)并未复制给前者,相当于这两个都同时指向同一地址,造成或释放两次内存。
深拷贝上面例子可以看到,会给它新申请一个空间。
注意:(引用)“如果需要析构函数,则一定需要拷贝构造函数和赋值操作符。”
什么情况使用复制构造函数:
类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
(1)一个对象以值传递的方式传入函数体
(2)一个对象以值传递的方式从函数返回
(3)一个对象需要通过另外一个对象进行初始化。
同时别人推荐的读的文章:https://blog.csdn.net/fdsafwagdagadg6576/article/details/51723823
想要了解跟多可以了解一下这篇文章:《面向对象进价--拷贝构造函数》
然后可以看下例子:多继承的例子(附详解)