什么是copy构造函数
首先对于普通类型的对象来说,它们之间的复制是很简单的。就类对象而言,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。
copy构造函数调用时机
1. 对象需要通过另外一个对象进行初始化
#include "iostream"
using namespace std;
class Test{
public:
Test(int a=0,int b=0){
m_a=a;
m_b=b;
cout<<"有参数构造函数"<<endl;
}
//赋值构造函数(copy构造函数)
Test(const Test&obj){
cout<<"copy构造函数"<<endl;
m_a=obj.m_a+100;
m_b=obj.m_b+100;
cout<<"m_a="<<m_a<<endl;
cout<<"m_b="<<m_b<<endl;
}
~Test(){
cout<<"析构函数"<<endl;
}
protected:
private:
int m_a;
int m_b;
};
//1 copy构造函数 (用一个对象初始化另一个对象)
void main(){
Test t1(1,2);//有参构造函数
Test t0(3,4);//有参构造函数
//Test t2=t1;
Test t2(t1);//copy构造函数
system("pause");
}
2.对象以值传递的方式传入函数参数
#include "iostream"
using namespace std;
class Location
{
public:
Location(int xx=0,int yy=0){
X=xx;
Y=yy;
cout<<"有参构造函数"<<endl;
}
Location(const Location&obj){
X=obj.X+1;
Y=obj.Y+1;
cout<<"copy构造函数"<<endl;
}
~Location(){
cout<<X <<" "<< Y <<"析构函数"<<endl;
}
int getX(){
return X;
}
int getY(){
return Y;
}
private:
int X;
int Y;
};
void f(Location p){
cout<<p.getX()<<endl;
}
void playobj(){
Location a(1,2);
Location b=a;//copy构造函数
f(b);//实参初始化形参,会调用copy构造函数
}
void main(){
playobj();
system("pause");
}
调用f()时,会产生以下几个重要步骤:
(1).b对象传入形参时,会先会产生一个临时变量,就叫 c 吧。
(2).然后调用拷贝构造函数把b的值给c。
(3).等f()执行完后, 析构掉c对象。
3. 对象以值传递的方式从函数返回
#include "iostream"
using namespace std;
class Location
{
public:
Location(int xx=0,int yy=0){
X=xx;
Y=yy;
cout<<"有参构造函数"<<endl;
}
Location(const Location&obj){
X=obj.X+1;
Y=obj.Y+1;
cout<<"copy构造函数"<<endl;
}
~Location(){
cout<<X <<" "<< Y <<"析构函数"<<endl;
}
int getX(){
return X;
}
int getY(){
return Y;
}
private:
int X;
int Y;
};
Location g(){
Location A(1,2);
return A;//copy构造函数
}
void playobj(){
g();//g返回了一个匿名对象,A是局部变量,无法返回
}
void playobj2(){
//用匿名对象初始化m,把匿名对象转成m(扶正)。不会被析构,playobj2结束时候析构
Location m= g();//g返回了一个匿名对象,A是局部变量,无法返回
cout<<"-------------"<<endl;
}
void playobj3(){
Location m2(1,2);
m2= g();
cout<<"-------------"<<endl;
}
void main(){
playobj3();
system("pause");
}
当g()函数执行到return时,会产生以下几个重要步骤:
(1). 先会产生一个临时变量,就叫XXXX吧。
(2). 然后调用拷贝构造函数把A的值给XXXX。
(3). 在函数执行到最后先析构A局部变量。
(4). 等g()执行完后再析构掉XXXX对象。
此处析构两次哦。(A和XXXX)
注意:
当调用playobj2()时候,A是局部变量,无法返回,g返回了一个匿名对象,用匿名对象初始化m,把匿名对象转成m(扶正)。不会被析构,playobj2结束时候析构。
因此结果: