首先我们了解复制构造函数起作用的三种情况:
1.当用一个对象去初始化同类的另一个对象时。
A a2(a1 );
A a2 = a1; //初始化语句,非赋值语句
2.如果某函数有一个参数是类 A 的对象, 那么该函数被调用时,类A的复制构造函数将被调用。
class A
{ public:
A() { };
A( A & a)
{ cout << "Copy constructor called" <<endl;
}
};
void Func(A a1){ }
int main()
{
A a2;
·Func(a2);
return 0;
}
程序输出结果为: Copy constructor called
3.如果函数的返回值是类A的对象时,则函数返回时, A的复制构造函数被调用:
class A
{ public:
int v;
A(int n) { v = n; };
A( const A & a) { v = a.v; cout << "Copy constructor called" <<endl; }
};
A Func() { A b(4); return b; }
int main()
{ cout << Func().v << endl; return 0; }
输出结果: Copy constructor called
4
ok,理解上面的复制构造函数起作用的情况之后我们考虑第二种情况 Func(a2); 。
在作为函数参数是,为什么也会调用复制构造函数?原因是实际上将a2作为实参传递给了形参 A a1,即A a1=a2 ,和第一种情况一致故调用了复制构造函数。
既然如此,重点来了。假如复制构造函数参数不是引用类型的话,即我们的复制构造函数写为 A (A a){ } , 那么将使得
A a2(a1 ) 变成a1作为实参传值给 A a2(A a ),即形参 A a = a1,因为复制构造函数的形参 a 没有被初始化, 所以A a = a1 继续调用复制构造函数,接下来的是构造a,也就是 a.A(a1),必然又会有a1传给A(A a), 即 A a=a1;那么又会触发复制构造函数,如此将永远的递归下去。
说明拷贝构造函数的参数使用引用类型,是避免拷贝构造函数无限制的递归下去。