默认的拷贝构造函数与对象的浅拷贝问题
如果定义类时,没有为其声明拷贝构造函数,则编译器会为类自动生成一个拷贝构造函数,这个由编译器自动生成的拷贝构造函数称为默认的拷贝构造函数。默认的拷贝构造函数的功能就是把参数对象内容按字节拷贝给当前正在创建的对象。
对象的浅拷贝:
#include<iostream>
using namespace std;
class A
{
public:
A()
{
numptr = new int(1);
}
A(int num)
{
numptr = new int(num);
}
~A()
{
delete numptr;
}
void setnum(int num)
{
*numptr = num;
}
int getnum()
{
return *numptr;
}
private:
int *numptr;
};
void main()
{
A a1(10);
A a2=a1;
cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;
cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;
a1.setnum(20);
cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;
cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;
}
运行结果:
对象a1中存放的整数位:10
对象a2中存放的整数位:10
对象a1中存放的整数位:20
对象a2中存放的整数位:20
分析:
对象的浅拷贝是产生这种现象的根本原因:
当执行语句A a2=a1时,需要调用默认拷贝构造函数,该函数a1按字节拷贝给对象a2,导致对象a1的整数指针numptr和对象a2的整数指针numptr指向“堆”中的同一个整数,所以当通过对象a1的成员numptr修改其指向的整数值时,自然会影响到对象a2。这种情况称为对象的浅拷贝。
对象间正确的拷贝方法应该使得不同的对象间不存在任何共享数据,称这种拷贝为深拷贝
解决方案:自定义拷贝构造函数
为类添加拷贝构造函数,以实现对象的深拷贝:
#include<iostream>
using namespace std;
class A
{
public:
A()
{
numptr = new int(1);
}
A(int num)
{
numptr = new int(num);
}
A(A&);
~A()
{
delete numptr;
}
void setnum(int num)
{
*numptr = num;
}
int getnum()
{
return *numptr;
}
private:
int *numptr;
};
A::A(A& a)
{
numptr= new int(*a.numptr);
cout<< “类的拷贝构造函数被调用”<<endl
}
void main()
{
A a1(10);
A a2=a1;
cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;
cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;
a1.setnum(20);
cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;
cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;
}
运行结果:
对象a1中存放的整数位:10
对象a2中存放的整数位:10
对象a1中存放的整数位:20
对象a2中存放的整数位:10
由赋值运算操作引发的对象浅拷贝
#include<iostream>
using namespace std;
class A
{
public:
A()
{
numptr = new int(1);
}
A(int num)
{
numptr = new int(num);
}
A(A&);
~A()
{
delete numptr;
}
void setnum(int num)
{
*numptr = num;
}
int getnum()
{
return *numptr;
}
private:
int *numptr;
};
A::A(A& a)
{
numptr= new int(*a.numptr);
cout<< “类的拷贝构造函数被调用”<<endl
}
void main()
{
A a1(10);
A a2;
a2=a1;
cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;
cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;
a1.setnum(20);
cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;
cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;
}
运行结果:
对象a1中存放的整数位:10
对象a2中存放的整数位:10
对象a1中存放的整数位:20
对象a2中存放的整数位:20
该程序是a2=a1使用了赋值操作符,默认情况下的赋值操作所完成的任务就是将赋值号右边的对象内容按字节拷贝给赋值号左边的对象,则也出现了浅拷贝现象。
解决:自定义赋值运算符
#include<iostream>
using namespace std;
class A
{
public:
A()
{
numptr = new int(1);
}
A(int num)
{
numptr = new int(num);
}
A(A&);
~A()
{
delete numptr;
}
void setnum(int num)
{
*numptr = num;
}
int getnum()
{
return *numptr;
}
A&operator=(A);
private:
int *numptr;
};
A::A(A& a)
{
numptr= new int(*a.numptr);
cout<< “类的拷贝构造函数被调用”<<endl
}
A& A::operator =(A a)
{
numptr= new int(*a.numptr);
return*this;
}
void main()
{
A a1(10);
A a2;
a2=a1;
cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;
cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;
a1.setnum(20);
cout<<“对象a1中存放的整数为:”<<a1.getnum()<<endl;
cout<<“对象a2中存放的整数为:”<<a2.getnum()<<endl;
}
运行结果:
对象a1中存放的整数位:10
对象a2中存放的整数位:10
对象a1中存放的整数位:20
对象a2中存放的整数位:10