原因:避免拷贝构造函数无限制的递归而导致栈溢出。
C++
#include <iostream>
using namespace std;
class A
{
private:
int val;
public:
A(int tmp) : val(tmp) // 带参数构造函数
{
cout << "A(int tmp)" << endl;
}
A(const A &tmp) // 拷贝构造函数
{
cout << "A(const A &tmp)" << endl;
val = tmp.val;
}
A &operator=(const A &tmp) // 赋值运算符重载
{
cout << "A &operator=(const A &tmp)" << endl;
val = tmp.val;
return *this;
}
void fun(A tmp)
{
}
};
int main()
{
A ex1(1);
A ex2(2);
A ex3 = ex1;
ex2 = ex1;
ex2.fun(ex1);
return 0;
}
/*
运行结果:
A(int tmp)
A(int tmp)
A(const A &tmp)
A &operator=(const A &tmp)
A(const A &tmp)
*/
对象 ex2 已经实例化了,不需要构造,此时只是将 ex1 赋值给 ex2,只会调用赋值运算符的重载;但是 ex3 还没有实例化,因此调用的是拷贝构造函数,构造出 ex3,而不是赋值函数,这里涉及到构造函数的隐式调用。
构造 ex3,实质上是 ex3.A(ex1);,假如拷贝构造函数参数不是引用类型,那么将使得 ex3.A(ex1); 相当于 ex1 作为函数 A(const A tmp) 的实参,在参数传递时相当于 A tmp = ex1,因为 tmp 没有被初始化,所以在 A tmp = ex1 中继续调用拷贝构造函数,接下来的是构造 tmp,也就是 tmp.A(ex1) ,必然又会有 ex1 作为函数 A(const A tmp); 的实参,在参数传递时相当于即 A tmp = ex1,那么又会触发拷贝构造函数,就这下永远的递归下去。
ex1 作为参数传递给 fun 函数, 即 A tmp = ex1;,这个过程会调用拷贝构造函数进行初始化。
直接初始化和拷贝初始化时
C++
string dots("zhang"); //直接初始化
string dots = "zhang" //拷贝初始化
3.何时调用复制构造函数:
新建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用。这在很多情况下都可能发生,最常见的情况是新对象显式地初始化为现有的对象。例如,假设 motto 是一个 StringBad 对象,则下面 4 种声明都将调用复制构造函数:
C++
StringBad ditto(motto);
StringBad metoo = motto;
StringBad also = StringBad(motto);
StringBad * pStringBad = new StringBad(motto);
其中中间的 2 种声明可能会使用复制构造函数直接创建 metoo 和 also ,也可能使用复制构造函数生成一个临时对象,然后将临时对象的内容赋给 metoo 和 also,这取决于具体的实现。最后一种声明使用 motto 初始化一个匿名对象,并将新对象的地址赋给 pStringBad 指针。
阅读量:227
点赞量:0
收藏量:0