一、为什么需要拷贝构造函数?
拷贝构造函数是一种特殊的构造函数,同样是初始化一个对象,不过其状态依赖于被拷贝对象。
二、什么是拷贝构造
如果一个构造函数的第一个参数是一个自身类类型的引用,且任何额外参数都有默认值。则此构造函数是拷贝构造函数。
class A
{
A(const A &){};
}
三、什么时候调用拷贝构造
- 拷贝初始化(
b=a
b(a)
) - 非引参数传入传出
- 容器、聚合类列表初始化
- 容器插入等操作(
push_back()
insert()
)
注:push_back将会先执行拷贝操作后插入容器。
聚合类类似于C语言的结构体,它满足以下要求:
- 所有成员都是public的
- 没有定义任何构造函数
- 没有类内初值
- 没有基类和virtual
拷贝构造函数的参数必须是自身类类型的引用,如果不这样的话,调用永不停止。一个使用非引用形参传递的函数在被调用时将会做一个额外的操作,以非引用方式调用拷贝构造函数,若拷贝构造函数成功返回将会继续执行函数体内容,事实上,这种情况无法返回,因为非引用方式调用拷贝构造将会继续以非引用调用另一次的拷贝构造函数调用,同理,另一次的拷贝构造将会继续以非引用方式调用另另一个拷贝构造…,整个调用过程就在不停的调用拷贝构造函数,形成递归调用。
四、怎么使用拷贝构造函数
class TA
{
public:
TA(){std::cout<<"构造函数调用"<<endl;}
// TA(const TA &)=delete;
TA(const TA &){cout<<"拷贝构造函数调用"<<endl;}
int c=3;
int d=4;
};
struct C
{
int a;
int b;
class TA ta;
};
int main()
{
class TA ta;
class TA tb=ta;//拷贝初始化
fun_passby_value(ta);//传入非引用值
fun_returnby_value();//返回非引用值
struct TA arrC[10]={ta,ta,ta,ta};//花括号数组相应成员的拷贝构造
struct C cc1={1,2,ta};//花括号聚合类相应成员的拷贝构造
//cc1={2,4,ta};//OK!
}
void fun_passby_value(class TA a)
{
}
class TA fun_returnby_value()
{
class TA d;
return d;
}
五、其他注意事项
为了效率,拷贝构造函数可能会被编译器优化而进行直接初始化。虽然编译器进行了优化,但是对应的拷贝访问控制仍然有效(不能是delete
或者private
)。