复制构造函数
复制构造函数专门是用一个对象完成另外一个【声明的】对象的初始化
如下面的代码所示
#include <iostream>
using namespace std;
class Test
{
private :
int height;
public :
Test(int height_) : height(height_)
{
cout << "调用了普通构造函数噢\n";
}
// private :
Test(const Test & t) : height(t.height)
{
cout<< "调用了复制构造函数噢\n";
}
public :
Test & operator=(const Test & t)
{
if(this==&t)
return *this;
cout << "调用了赋值运算符噢" << endl;
height = t.height;
return *this;
}
};
int main()
{
Test obj1(188);
Test obj2 = obj1;
obj2 = obj1;//不是【声明】,因此此行属于调用了赋值运算符!!!
Test obj3 = Test(188);
cout << "-----------------------\n";
obj3 = 190;
Test obj4 = 190;//原因同Test obj3 = Test(188);
}
对Test obj1(188);解释:
就是使用了普通构造函数
对Test obj2 = obj1;解释:
就是用复制构造函数,在声明的时候用对象初始化另外一个对象
复制构造函数负责先创建一个对象,再把=右边的用来初始化声明的对象
对obj2 = obj1;解释
由于不是声明时创建对象,只是普通的对象赋值,符合赋值运算符的调用条件,
因此调用的是赋值运算符
对Test obj3 = Test(188);解释
原来是:把一个声明的对象先创建,并在声明时用Test(188)初始化obj3,所以调用复制构造函数,
但是编译器优化了该步骤,不需要频繁的调用复制构造函数和赋值运算符
直接就给你一步到位,完成了对象的初始化,
普通构造函数创建出来的就是你声明的对象,相当于Test obj3(188);
从而使得看起来不需要复制构造函数的样子,
但是,如果你私有了复制构造函数,
就不会为你做这个只用普通构造函数初始化对象的优化,从而需要复制构造函数
但是你又私有了复制构造函数,类外不能用,因此编译报错,在上下文中私有化了复制构造函数
对obj3 = 190;的解释
编译器发现190可以直接转化为类对象,于是调用Test(int),又发现可以优化
情况又和Test obj3 = Test(188);一样了
输出结果
解开了private注释后的编译报错
参考文章:
C++的一大误区——深入解释直接初始化与复制初始化的区别
C++ Primer 原文理论支持的编译器优化:442页,第五版中文版
复制构造函数调用条件
①声明并初始化(非引用)对象的时候调用
②对象按值传递和按值返回对象
③花括号列表初始化数组或者聚合类成员
④某些类类型还会对他们所分配的对象进行拷贝初始化,,例如我们初始化标准容器或
是调用其insert或push成员,容器回对其元素进行拷贝初始化,与之相对,用emplace成员
创建的元素都进行直接初始化,
注:
②的情况都和①是完全一样的,返回值相当于一个匿名的变量,形参就是相当于是声明了对象
写在最后
纸上觉来终觉浅,听别人说总是印象不深刻,必须要自己多手打代码验证一下