跳至主要內容

拷贝构造函数

张威大约 4 分钟c/c++类和对象

拷贝构造函数

img
img

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;

此时需要重新显式定义拷贝构造函数,让两个指针指向不同堆空间的方式叫深拷贝源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响

在这里插入图片描述
在这里插入图片描述

拷贝构造函数的调用时机

  1. 当用一个已经存在的对象初始化另一个新对象时,会调用拷贝构造函数。
  2. 当实参和形参都是对象,进行实参与形参的结合时,会调用拷贝构造函数。
  3. 当函数的返回值是对象,函数调用完成返回时,会调用拷贝构造函数。(优化选项-fno-elide-constructors)

Q:拷贝构造函数参数中的可以去掉吗?

不能去掉,如果去掉引用符号,在满足拷贝构造函数的情况,会满足拷贝构造函数的用 一个已经存在的对象初始化一个新对象 的调用时机,然后进行调用拷贝构造函数函数的参数是会入栈,这样的话栈空间肯定会溢出的,所以引用符号不能去掉

Q:拷贝构造函数参数中的可以去掉吗?

不能去掉,当传递的是(临时对象、临时变量、匿名对象)的时候,会返回报错(非const左值引用不能绑定到右值),当传递临时对象的时候,就会报错

Q:为什么拷贝时候要使用,使用memcpy函数补上更简单吗?

因为在进行数据拷贝时候,如果是整型,不会占用整型之外的资源,进行memcpy拷贝没有问题。