用到拷贝构造函数的地方有3种情况:
1)一个对象用于给另外一个对象进行初始化(赋值初始化)
2)一个对象作为函数参数,以值传递的方式传入函数体
3)一个对象作为函数返回值,以值传递的方式从函数返回
为什么要用到拷贝构造函数
原则:对于凡是包含动态分配成员或包含指针成员的类都应该提供拷贝构造函数
对于第一种情况,先用一个例子进行以下的说明:
//这个类的主要特点是包含指向其他资源的指针,pBuffer指向堆中动态分配的一段内存空间。
class CExample
{
private:
char* pBuffer;//类的对象中包含指针,指向动态分配的内存资源
int nSize;
public:
CExample()//构造函数
{
pBuffer = NULL;
nSize = 0;
}
~CExample()//析构函数
{
delete[] pBuffer;
}
void Init(int n)
{
pBuffer = new char[n];
nSize = n;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CExample theObjone;
theObjone.Init(40);
//现在需要另一个对象,并将它初始化为theObjone
CExample theObjtwo = theObjone;
getchar();
return 0;
}
<span style="white-space:pre"> </span>语句"CExample theObjtwo = thObjone;"用theObjone初始化theObjtwo
<span style="white-space:pre"> </span>此语句的具体过程:首先,建立对象theObjtwo,然后,调用其构造函数,然后,成员被复制初始化。
<span style="white-space:pre"> </span>其完成方式是内存拷贝,复制所有成员的值。完成后,theObjtwo.pBuffer == theObjone.pBuffer
<span style="white-space:pre"> </span>即,它们指向同样的地方,指针虽然复制了,但所指向的空间并没有复制,儿时由两个对象共用了。这样不符合要求,对象之间部队里了,并为空间的删除带来隐患。
这就是引入<span style="background-color: rgb(204, 51, 204);">拷贝构造函数</span>的初衷。
对于第二,第三种情况,如果不使用拷贝构造函数,就会导致一个指针指向已经被删除的内存空间。
第二种情况,对象按值传递:当对象直接作为参数传给函数时,函数将简历对象的
临时拷贝,这个拷贝过程也将调用拷贝构造函数。
bool testfunc(CExample obj);
testfunc(theObjone);
bool testfunc(CExample obj)
{}
<span style="white-space:pre"> </span>第三种情况:当函数中的局部对象作为返回值被返回给函数调用者时,也将建立此局部对象的一个<strong>临时拷贝</strong>,拷贝构造函数也将被调用。
CTest func()
{
CTest theTest;
return theTest;
}
拷贝构造函数的样子
格式:类名(const类名&对象名)------CExample(const CExample&);
参数是常量对象的引用。由于拷贝构造函数的目的是成员复制,不应修改原对象,所以建议使用const关键字