拷贝构造函数
- 以值传递的方式调用函数时,如果实参为对象,会调用拷贝构造函数。
- 函数以值的方式返回对象时,可能会调用拷贝构造函数(VS会调用,Linux不会,g++编译器做了优化)
- 浅拷贝存在的问题
类似于构造函数和析构函数,拷贝构造函数在对象拷贝的时候自动调用
下面两种方法是拷贝构造函数的调用场景:
类名 新对象名(已存在的对象名);
类名 新对象名=已存在的对象名;
自定义拷贝构造函数方法:类的常引用
其中g和g22对象为无效值的原因是:
在我们定义的拷贝构造函数时,没有给g和g22对象的属性初始化。
编译器默认提供的拷贝构造函数不是空实现:
我们将自定义的拷贝构造函数注释掉,将调用系统提供的拷贝构造函数
明显看出,拷贝构造函数将类的所有参数拷贝到另一个类中。
以值传递的方式调用函数时,如果实参为对象,会调用拷贝构造函数。
这个是一个容易忽视的使用细节。
这里形参类的属性还是无效的值,原因是:
我们自定义的拷贝构造函数没有进行传参。
函数以值的方式返回对象时,可能会调用拷贝构造函数(VS会调用,Linux不会,g++编译器做了优化)
在函数返回值赋值给g2的时候调用了拷贝构造函数。
局部变量g1在函数调用结束就析构销毁了。
g2中属性是无效值的原因是:
在自定义的拷贝构造函数里面没有赋值。
但是在linux中,函数返回值赋值给实参不会调用拷贝构造函数,
底层原因是:在函数运行结束后,局部变量g1没有被析构,换了个名字g2作为实参继续存在,这样就省略了赋值(调用拷贝构造函数)和销毁局部变量(调用析构函数)这两个操作。
浅拷贝存在的问题
存在两个对象中的指针指向同一块内存空间,如果其中一个对象的指针释放掉,另一个对象中的指针就成为了野指针,访问野指针会程序崩溃。
详细代码见这篇博文
(编译器默认提供的拷贝构造函数是浅拷贝)
解决方法:在拷贝构造函数中使用深拷贝。
CGirl(const CGirl& gg)
{
m_name = gg.m_name; m_age = gg.m_age;
m_ptr = new int; // 分配内存。
// *m_ptr = *gg.m_ptr; // 拷贝数据。
memcpy(m_ptr, gg.m_ptr, sizeof(int)); // 拷贝数据。
cout << "调用了CGirl(const CGirl &gg)拷贝构造函数。\n";
}