拷贝函数就是编译器自动帮你拷贝对象,自己却不需要实现拷贝方法。
那么我一直都有一个疑问,那么编译器到底有没有在类中给我们创建拷贝构造函数呢? 拷贝构造函数真的存在吗?
首先假设我们有下面两个类,一个Base类,一个Base的子类Child.
1 | class Base { |
我们在Child类中自己定义了一个拷贝构造函数,那么子类肯定存在,如下图:
我们跳进这个function看一下里面发生了什么:
我们可以发现,这个function的确是我们自己写的拷贝构造函数。但是奇怪的是,在我们自己创建的拷贝构造函数里面竟然又调用了一个函数,但是我们自己并没有这么写呀。我们跳进去看一下这个是什么函数:
原来我们自己创造的拷贝构造函数自动调用了父类的空构造函数呀。这不就是普通构造函数的特点吗:如果不指定父类构造函数,那么自动调用父类的空构造函数。
这里可以看出,子类自己定义拷贝构造函数并不会自动调用父类的构造函数,而是和别的构造函数一样,自动调用父类的空构造函数
那么到底编译器有没有创建这个拷贝构造函数呢?
我们可以直接使用父类的所谓”拷贝构造函数”试一下:
我们可以看到,我们调用了所谓的”拷贝构造函数”,但是底层汇编语言只是简单的拷贝,并没有为我们开辟一个所谓的”拷贝构造函数”
那么讲到对象拷贝了,除了拷贝构造函数,还有一种方式为重载”=”操作符。
其实”=”操作符编译器也帮我们实现了对象的浅拷贝,底层和拷贝构造函数实现是一样的。
但是如果重载,方式就不一样的,一个是构造函数重载,一个是普通函数重载。
如果我们使用拷贝构造函数,那么我们overwrite的就是构造函数,要使用构造函数的方式使用父类的构造函数 (“:ParentConstructor(arg1, arg2,…)”)。
如果我们使用”=” operator,那么我们就相当于overwrite普通的函数,这个时候要用普通函数的方法来使用父类方法(“ParentClass::operator=(arg1)”)。
Conclusion:
拷贝构造函数其实就是一个假函数,编译器并没有为我们创造一个函数来copy对象。编译器做的只是简单的复制数据。而且是 浅拷贝:只简单拷贝数据,不拷贝指针里面的东西。
如果需要 深拷贝,则需要自己去写一个拷贝函数。