1. 深拷贝和浅拷贝
1)默认复制构造函数可以完成对象的数据成员值简单的复制
2)对象的数据资源是由指针指示的堆时,默认复制构造函数仅作指针值复制
1. 1 浅拷贝
1)对象中什么样的操作的浅拷贝?如下代码,可以看到这个类只有构造函数以及析构函数,当执行Name obj2 = obj1语句时,浅拷贝就发生了,回报错程序,为什么?
class Name
{
public:
Name(const char *pname) //构造函数
{
size = strlen(pname);
pName = (char *)malloc(size + 1);
strcpy(pName, pname);
}
~Name()
{
cout<<"开始析构"<<endl;
if (pName!=NULL)
{
free(pName);
pName = NULL;
size = 0;
}
}
protected:
private:
char *pName;
int size;
};
void playObj()
{
Name obj1("abcdefg");
Name obj2 = obj1; //obj2创建并初始化
}
void main()
{
playObj();
system("pause");
}
首先我们知道先创建的对象后析构,因此在执行这个语句中obj1已经初始化然后用它这个对象去初始化另一个对象obj2,但是由于这个类结构中不含有赋值构造函数,此时C++编译器就会调用默认的赋值构造函数,【默认复制构造函数仅作简单指针值复制】即就仅仅是将obj1中的指针变量指向的地址与len值赋值到obj2对象的变量中,并没有开辟新的空间,此时obj1与obj2指向堆中同一个空间。最后就是赋值完成后,obj2要进行析构了,执行free(pName);,堆中空间被释放且obj2中的p=NULL;但是当obj2析构完后到了obj1析构时,此时obj1指针p由于obj2的析构已经是一个野指针,而自己又要析构一次,即又要执行free(pName)进行对空间释放;但已经释放且指针指向为野指针(被析构两次)编译运行时会触发程序中断。
//对象的初始化 和 对象之间=号操作是两个不同的概念
void playObj()
{
Name obj1("obj1.....");
Name obj2 = obj1; //obj2创建并初始化
Name obj3("obj3...");
//重载=号操作符
obj2 = obj3; //=号操作
cout<<"业务操作。。。5000"<<endl;
}
2)
1.2 深拷贝
1)那么针对上面问题,怎么使得对象的初始化成功呢?即我们的目标是让希望在堆中开辟一个同样大小的新空间,再将obj1的值赋值到obj2的指针指向的新空间中,然后当在进行析构时,两个对象互补影响【实现代码如下】
Name(Name &obj)
{
//用obj来初始化自己
pName = (char *)malloc(obj.size + 1);
strcpy(pName, obj.pName);
size = obj.size;
}
2)至于图二中的浅拷贝形势,要解决就需要重载=操作符才行