拷贝构造函数能够使类具有自行赋值本类对象的能力,即可生成一个对象的副本,它只以本类对象的引用作为其唯一的形参,该函数的定义形式如下:
class 类名
{
public:
类名(形参);//(构造函数)
类名(类名 &对象名);//(拷贝构造函数)
..................
};
类名::类名(类名 &对象名)//拷贝构造函数的实现
{
函数体
}
拷贝构造函数举例:
class Point
{
public:
Point(int xx=0,int yy=0) //构造函数
{
X=xx;
Y=yy;
}
Point(Point &p); //拷贝构造函数
int GetX() {return X;}
int GetY() {return Y;}
private:
int X,Y;
};
Point::Point(Point &p)
{
X=p.X;
Y=p.Y;
cout<<"拷贝构造函数被调用"<<endl;
}
拷贝构造函数被自动调用执行的三种情况:
1) 当用类的一个对象去初始化该类的另一个对象时
void main(void)
{
Point A(1,2);
Point B(A);//拷贝构造函数被调用
cout<<B.GetX()<<endl;
}
2)若函数的形参为类对象,调用函数,实参赋值给形参时
void fun1(Point p)
{
cout<<p.GetX()<<endl;
}
void main()
{
Point A(1,2);
fun1(A);//调用拷贝构造函数
}
3) 若函数的返回值是类的对象,函数执行完成返回调用时
Point fun2()
{
Point A(1,2);
return A;//调用拷贝构造函数
}
void main()
{
Point B;
B=fun2();
}
如果程序员没有为类声明拷贝初始化构造函数,则编译器自己生成一个拷贝构造函数,该函数的功能是:用作为初始值的每个数据成员的值,初始化将要建立的对象的对应的数据成员。
浅拷贝
由默认的拷贝构造函数将已有的对象的数据成员一一赋值给同类的新对象的各数据成员来构造新对象的方法就是浅拷贝,也即是成员级拷贝。
不足之处:
若用户未提供类的显示拷贝构造函数,而让系统去执行缺省的拷贝构造函数,只进行对象间的原样拷贝,则会出现两个对象拥有同一个资源,即拥有同一块系统堆空间的情况(因为进行了原样拷贝,从而使得两个不同对象的地址值完全相同)。当对象被析构时,则会出现同一资源被释放了两次的错误。
深拷贝
为了克服浅拷贝的不足,用户必须给出显式的拷贝构造函数,以实现“深拷贝”的功能:在拷贝构造函数中,首先要动态申请存储空间,并向该空间拷贝原对象的内容。
显式拷贝构造函数例子:
person(person &p)
{
cout<<"copying"<<p.pName<<"into its own block"<<endl;
pName=new char[strlen(p.pName)+1];
strcpy(pName,p.pName);
}