一、拷贝构造函数
1、拷贝构造函数定义
class A
{
private:
int _a;
public:
A(){};
A(const A&); //定义拷贝构造函数,一定要有一个实现
};
A::A(const A& Aa)
{
cout<<"拷贝构造"<<endl;
}
2、调用拷贝构造函数的时机
//E1、声明语句中,一个对象初始化另一个对象,前提是类必须存在拷贝构造函数
A obj1;
A obj2 = obj1;
//E2、对象作为参数
void get(A obj) {} //调用这个函数的时候,先会调用拷贝构造函数
//E3、函数返回一个对象
A get(){ A obj ; return obj;} //
二、C++浅拷贝和深拷贝【7】
1、浅拷贝
class A
{
private:
int _a;
public:
A(){};
A(const A&);
void setData(int a1){ _a = a1; }
void Output(){ cout<<"A::a = "<<_a<<endl; }
};
A::A(const A& Aa) //如果是浅拷贝,则,在这里直接将一个对象的值赋值给另外一个对象
{
_a = Aa._a;
cout<<"拷贝构造"<<endl;
}
int main(int argc, char* argv[])
{
A a;
a.setData(10);
A b = a;
b.Output();
}
2、深拷贝
CExample::CExample(const CExample& RightSides)
{
pBuffer=NULL;
*this=RightSides //调用重载后的"="
}
//赋值操作符重载
CExample & CExample::operator = (const CExample& RightSides)
{
nSize=RightSides.nSize; //复制常规成员
char *temp=new char[nSize]; //复制指针指向的内容
memcpy(temp,RightSides.pBuffer,nSize*sizeof(char));
delete []pBuffer; //删除原指针指向内容 (将删除操作放在后面,避免X=X特殊情况下,内容的丢失)
pBuffer=temp; //建立新指向
return *this
}
【点评】深拷贝,会将对象指针指向的动态内存中的值,拷贝到另外一个对象中,以防止内存泄露。另外,拷贝是将一个有值的对象赋值给空值的对象,而"赋值"操作符是将原来有值的对象中的值覆盖,调用的是"=重载函数"。
三、拷贝构造函数调用时机
1、对象作为参数,调用构造函数
//浅拷贝中的例子加入如下代码
bool SetA(A a)
{
return true;
}
//void main()
SetA(a);
//汇编代码
53: A b = a;
004012CA lea eax,[ebp-4] //a的指针
004012CD push eax
004012CE lea ecx,[ebp-8] //b的指针
004012D1 call @ILT+60(A::A) (00401041)
54: b.Output();
004012D6 lea ecx,[ebp-8]
004012D9 call @ILT+15(A::Output) (00401014)
55: SetA(a);
004012DE push ecx
004012DF mov ecx,esp //当前栈已经开辟了临时对象空间,相当于b的指针
004012E1 lea edx,[ebp-4]
004012E4 push edx //a的指针
004012E5 call @ILT+60(A::A) (00401041)
004012EA call @ILT+10(SetA) (0040100f) //已经拷贝了到了ecx,所以就直接调用SetA(),此时esp就是临时对象的指针
004012EF add esp,4 //esp+4 还是指向临时对象
2、返回一个对象
CExample GetExpFun()
{
return g_objExp;
}
objExp2 = GetExpFunc();
004013E4 lea ecx,[ebp-40h] //返回的临时对象空间是进入main函数的时候,提前分配好的。
004013E7 push ecx //先将对象压栈
004013E8 call @ILT+25(GetExpFun) //调用函数
【点评】 返回对象时,也是在当前栈分配了临时空间,会调用在函数中,调用拷贝构造函数,来赋值给临时空间。相当于一个中转战,先拷贝构造函数赋值给临时空间,再用它。
参考:1、C++拷贝构造函数(深拷贝、浅拷贝)
4、拷贝构造函数