1.拷贝构造函数
当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用。也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
一个对象以值传递的方式传入函数体
一个对象以值传递的方式从函数返回
一个对象需要通过另外一个对象进行初始化。
如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝。
2. 浅拷贝和深拷贝
在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。
深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。
3. 实例分析
(1) 浅拷贝
运行结果如下:
分析:
由于构造p2时采用默认构造函数且为浅拷贝,故 p1与 p2对象的 m_name 指向同一内存空间,故对 p2的 m_name 进行修改即为对 p1的 m_name 的修改。
(2) 深拷贝
手工添加拷贝构造函数,得到如下代码:
运行结果如下:
分析:
由于通过 p1构造 p2 时采用深拷贝,故二者的 m_name 分别指向不同的内存空间,二者互不影响。
4. 其他相关细节
对于如上的拷贝构造函数,若改写为如下:
则系统报错,原因是 person为 const 对象,仅能调用const成员函数,但是构造函数和析构函数是唯一不是const成员函数却可以被const对象调用的成员函数 。
若为了适应此写法,则应对 char * getName()函数作如下改动: