要想理解浅拷贝和深拷贝,我们不得不先从它的概念看起;
首先,所谓浅拷贝:就是由默认的拷贝构造函数所实现的数据成员逐一赋值,通常默认的拷贝构造函数式可以胜任次工作的,但若类中含有指针类型的数据,就按数据逐一赋值的发放产生错误。
浅拷贝代码:
#include<iostream.h>
#include<string.h>
class student
{
public:
student(char *n, float s)
{
cout<<"Constucting....<<endl;
name = new char[strlen(name) +1];
if(name != NULL)
{
strcpy(name, n);score = s;
}
}
~student()
{
cout<<"Distructing...<<endl;
name[0] = '\0';delete []name;
}
private:
char *name;
float score;
};
void main()
{
student stu("LiMing", 90);//调用构造函数,构造对象stu
student stu1 = stu; //调用默认的拷贝构造函数,把对象stu的数据成员逐个复制到stu1对应的数据中,但并没有新分配内存空间给stu1;
}
浅拷贝示意图
主程序结束时,对象逐个撤销,先撤销stu,调用析构函数,用delete释放动态分配的内存空间;撤销对象stu时,第二次调用析构函数,这时因为指针name所致空间已被释放,所以输出随机字符串;当执行delete时,企图释放同一空间,从而导致对同一内存的两次释放,引起错误;
解决浅拷贝方法:
显示的定义一个自定义的拷贝构造函数,使之不但复制数据成员,而且对对象stu和stu1分配各自的内存空间,这便是深拷贝;
深拷贝代码:
#include<iostream.h>
#include<string.h>
class student
{
public:
student(char *n, float s)
{
name = new char[strlen(name) +1];
if(name != NULL)
{
strcpy(name, n);
score = s;
}
}
~student()
{
name[0] = '\0';
delete []name;
}
student(student &st)
{
cout<<"Copy Conatructing..."<<endl;
name = new char[strlen(st.name) +1];
if(name != NULL)
{
strcpy(name, st.name);
score = st.score;
}
}
private:
char *name;
float score;
};
void main()
{
student stu("LiMing", 90);
student stu1 = stu;
}
深拷贝示意图
程序开始时,调用构造函数,构造对象stu,用new从内存中动态分配一块空间,字符指针name指向这块空间。
student stu1 = stu; //调用拷贝构造函数,把对象stu的数据成员逐个复制到stu1对应的数据中,并分配新内存空间给stu1;
主程序结束时,对象逐个撤销,先撤销stu1,调用析构函数,用delete释放动态分配给stu1的内存空间;撤销对象stu时,第二次调用析构函数,释放了分配给stu的内存空间;当执行delete时,从而避免了对同一内存的两次释放。
深拷贝与浅拷贝不同的是对于引用拷贝的处理,深拷贝将会在新对象中创建和原是对象中对应值类型的字段并且赋值。浅拷贝不会创建新引用类型,会返回相同的类型引用。深拷贝会重新创建新对象,返回新对象的引用字。
来自<<C++面向程序设计>>.