(一)引入
复制构造函数要求有一个类类型的引用参数:
类名::类名(const 类名& 应用名,…);
<pre name="code" class="cpp">class A
{
public:
A(int);
A(const A &,int =1);
…………
};
A a(1); //创建a,调用A(int) 一般构造函数
A b(a,0); //创建b,调用A(const A &,Int=1) 复制构造函数
A c=b; //创建c,调用A(const A &,Int=1) 复制构造函数
(二)调用复制构造函数的时机
当说明语句创建对象时、函数具有类类型传值参数、函数返回类类型时,会调用复制构造函数,下面具体说明后面2种情况。
1.类类型传值参数的函数
<pre name="code" class="cpp">class A
{
public:
A(int xx=0,int yy=0) { X=xx;,Y=yy;cout<<”gouzao”<<endl; }
A(constA & a)
{
X=a.X;
Y=a.Y;
cout<<”fuzhi gouzao”<<endl;
}
~A()
{
cout<<X<<”,”<<Y<<”xigou”<<endl;
}
int GetX()const {return X}
int GetY()const {return Y};
private:
int X,Y;
};
void f(A a)
{ cout<<”fun:”<<a.GetX()<<”,”<<a.GetY(); }
int main()
{
A t(1,2);
f(t);
}
运行结果:
gouzao //构造t
fuzhi goyuzao //调用函数法f(t)时,将实参t传给形参a,需要调用复制构造函数
fun:1,2
1,2xigou //析构形参a
1,2xigou //析构t
2.返回类类型的函数
<pre name="code" class="cpp">class A
{
public:
A(int xx=0,int yy=0) { X=xx;,Y=yy;cout<<”gouzao”<<endl; }
A(constA & a)
{
X=a.X;
Y=a.Y;
cout<<”fuzhi gouzao”<<endl;
}
~A()
{
cout<<X<<”,”<<Y<<”xigou”<<endl;
}
int GetX()const {return X}
int GetY()const {return Y};
private:
int X,Y;
};
A f()
{
A a(1,2);
return a; //将a返回,所以生成一个匿名(临时)对象x返回拷贝,而不会返回参数的a ------------关键点
}
int main()
{
A t;
t=f();
}
运行结果:
gouzao //构造t
gouzao //构造局部对象a
fuzhi goyuzao //创建一个临时对象x,并将其返回,复制给t,即(t=x)
1,2xigou //析构临时对象
1,2xigou //析构形参a
1,2xigou //析构t
(三)深复制与浅复制
当类的数据成员是简单数据结构时,一般是浅复制;
当类的数据成员资源使用指针指示的堆,用普通的复制方法只进行指针(地址)复制,不会重新分配内存空间。
class T
{
………….
protected:
char *pname;
int size;
}
T a(“123”),b;
b=a;
a b
'0' |
'1' |
'2' |
'\0' |
最后当b析构后,该内存空间已释放,但是a还要进行析构,这个时候就会出现“释放空指针”的错误。
要使上面的程序正常运行,需要自己定义复制构造函数: T(constT &obj);在这个复制构造函数里面开辟单独的内存空间即可