转自:http://www.cnblogs.com/dwdxdy/archive/2012/07/17/2594993.html
在C++中,调用拷贝构造函数有三种情况:
1.一个对象作为函数参数,以值传递的方式传入函数体.
2.一个对象作为函数返回值,以值传递的方式从函数返回.
3.一个对象用于给另外一个对象进行初始化(复制初始化).
拷贝构造函数必须以引用的形式传递(参数为引用值).其原因如下:
当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动的调用来生成函数中的对象.
这样会导致无限循环地调用拷贝构造函数,直至栈溢出.
以前,一直有个误解,以为以同类型的对象调用"="时,就会调用赋值符.参看以下的例子:
class CTest { public: CTest(); CTest(const CTest&); CTest& operator=(const CTest &); }; CTest::CTest() { cout<<"Constructor of CTest"<<endl; } CTest::CTest(const CTest& arg) { cout<<"Copy Constructor of CTest"<<endl; } CTest& CTest::operator=(const CTest& arg) { cout<<"Assign function of CTest"<<endl; } int main() { CTest a; CTest b(a); CTest c = a; a = c; return 0; }
按照以前的理解,第21~24行代码,应该分别调用构造函数,拷贝构造函数,赋值符函数,赋值符函数.
然而最终如下,不是如自己所想...说明以前的理解是错误的.
Constructor of CTest
Copy Constructor of CTest
Copy Constructor of CTest
Assign function of CTest
第23行代码调用的是拷贝构造函数,不是赋值符函数,但第24行代码调用的赋值符函数,不是拷贝构造函数.原因如下:
拷贝构造函数创建新的对象,而赋值符函数不创建新对象,它要求"="的左右对象均已存在,它的作用就是把"="右边的对象的值赋给左边的对象.
虽然编译器会提供拷贝构造函数和赋值符函数,但是有时候编译器提供的这些函数,并不能满足我们的需求,因而需要自定义拷贝构造函数和赋值函数.
这里就会引出一个新问题,什么时候需要自定义拷贝构造函数和赋值符函数.
简单的规则:如果需要定义一个非空的析构函数,那么,通常情况下也需要定义一个拷贝构造函数和赋值符函数.
通常的原则是:
1.对于凡是包含动态分配成员或包含指针成员的类都应该提供拷贝构造函数;
2.在提供拷贝构造函数的同时,还应该考虑重载"="赋值操作符,即提供赋值符函数.
当我们知道需要自定义拷贝构造函数和赋值符函数时,就得考虑如何良好的实现它们.
当自定义copying函数(包含拷贝构造函数和赋值符函数)时,需要确保以下两点:
1.复制所有的local成员变量
2.调用所有base classes内的适当的copying函数,完成基类的copying.