拷贝构造函数
大约 4 分钟
拷贝构造函数

C++中经常会使用一个变量初始化另一个变量,如
int x = 1;
int y = x;
我们希望这样的操作也能作用于自定义类类型,如
Point pt1(1, 2);
Point pt2 = pt1;
pt1对象已经存在,而pt2对象还不存在,所以也是这句创建了pt2对象,既然涉及到对象的创建,就必然需要调用构造函数,而这里会调用的就是复制构造函数,又称为拷贝构造函数。如果类中没有显式定义拷贝构造函数时,编译器会自动提供一个缺省的拷贝构造函数。其原型是:
类名::类名(const 类名 &);
缺省的拷贝构造函数
如果成员比较简单,缺省的拷贝构造函数已经可以满足需求了,所以可以不显式定义
Point::Point(const Point &rhs)
: _ix(rhs._ix)
, _iy(rhs._iy)
{
}
浅拷贝和深拷贝
只拷贝指针地址的方式,我们称为浅拷贝。

浅拷贝出错问题: 对象使用浅拷贝不一定有错,但是对象有,那么当发生浅拷贝时,两个对象不同的指针指向同一个资源。第一次析构将堆内存释放,。
class Computer
{
public:
Computer(const char *brand, double price)
: _brand(new char[strlen(brand) + 1]())
, _price(price)
{
cout << "Computer(const char *, double)" << endl;
}
Computer(const Computer &rhs) //缺省的拷贝构造函数
: _brand(rhs._brand) //浅拷贝
, _price(rhs._price)
{
}
Computer(const Computer &rhs)
: _brand(new char[strlen(rhs._brand) + 1]()) //深拷贝
, _price(rhs._price)
{
}
private:
char *_brand; //指向堆内存的指针
double _price;
};
//执行构造初始化
Computer pc1("Huawei Matebook14", 5699);
Computer pc2 = pc1;
此时需要重新显式定义拷贝构造函数,让两个指针指向不同堆空间的方式叫深拷贝,源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响

拷贝构造函数的调用时机
- 当用一个已经存在的对象初始化另一个新对象时,会调用拷贝构造函数。
- 当实参和形参都是对象,进行实参与形参的结合时,会调用拷贝构造函数。
- 当函数的返回值是对象,函数调用完成返回时,会调用拷贝构造函数。(优化选项
-fno-elide-constructors
)
Q:拷贝构造函数参数中的可以去掉吗?
不能去掉,如果去掉引用符号,在满足拷贝构造函数的情况,会满足拷贝构造函数的用 一个已经存在的对象初始化一个新对象 的调用时机,然后进行调用拷贝构造函数,函数的参数是会入栈,这样的话栈空间肯定会溢出的,所以引用符号不能去掉
Q:拷贝构造函数参数中的可以去掉吗?
不能去掉,当传递的是(临时对象、临时变量、匿名对象)的时候,会返回报错(非const左值引用不能绑定到右值),当传递临时对象的时候,就会报错
Q:为什么拷贝时候要使用,使用memcpy函数补上更简单吗?
因为在进行数据拷贝时候,如果是整型,不会占用整型之外的资源,进行memcpy拷贝没有问题。