1、C+拷贝构造函数,深拷贝,浅拷贝,无错误的浅拷贝,先看一个简单的例子,该例子是浅拷贝的典型代表,而且没有问题。 接下来看Example 1。,Cperson.h,#ifndef _CPERSON_H #define _CPERSON_Hclass Cperson public:Cperson(int age);void Print(void); private:int m_age; ;#endif,Cperson.cpp,#include“Cperson.h“ #includeCperson:Cperson(int age):m_age(age) void Cperson:Print(void
2、) cout“My age is “m_ageendl; ,Main.cpp,#include“Cperson.h“ #includevoid main(void) Cperson Tom(10);Tom.Print();Cperson Jim(Tom);Jim.Print(); ,结果,结果分析,对于语句Cperson Jim(Tom),我们并没有定义相应的拷贝构造函数,编译器将会自动生成一个默认的拷贝构造函数。 默认拷贝构造函数所做的工作是,将一个对象的全部数据成员赋值给另一个对象的数据成员。 C+把只对象数据成员简单赋值这种情况称为“浅拷贝”。,结果分析,听起来,编译器似乎很好,会提供一
3、个我们没有定义的拷贝构造函数,但这后面存在巨大的风险。 所以有些事情(拷贝构造函数)还是自力更生不接受外援的好。,有错误的浅拷贝,在接下来的Example 2中,我们将看到浅拷贝带来的错误。,Cperson.h,#ifndef _CPERSON_H #define _CPERSON_Hclass Cperson public:Cperson(int age,char *name);Cperson();void Print(void); private:int m_age;char *m_name; ;#endif,Cperson.cpp,#include“Cperson.h“ #include
4、 #includeCperson:Cperson(int age,char *name) m_name = new charstrlen(name) + 1;if(m_name != NULL)strcpy(m_name,name);m_age = age;coutm_name“的构造函数“endl; ,Cperson.cpp,Cperson:Cperson() cout“析构姓名:“m_nameendl;if(m_name != NULL)delete m_name; void Cperson:Print(void) cout“My age is “m_age“,My name is “m_
5、nameendl; ,Main.cpp,#include“Cperson.h“ #includevoid main(void) Cperson Tom(10,“Tom“);Tom.Print();Cperson Jim(Tom);Jim.Print(); ,结果,结果分析,可以看到,程序出现了错误。 在执行语句Cperson Tom(10,“Tom”)时,用new动态开辟了一段内存,用来存放”Tom”。 在执行Cperson Jim(Tom)时,只是将Tom的成员(Tom.m_age,Tom.m_name)赋值给Jim相应的成员。,结果分析,此时,Tom.m_name和Jim.m_name指向
6、同一内存空间,然而,系统并没给Jim.m_name开辟相应的内存空间。 执行完Jim.Print()后,开始执行析构函数,析构函数的执行顺序和对象构造函数的执行顺寻相反,所以先执行Jim的析构函数,执行完Jim的析构函数后,Jim.m_name所指的内存空间已经释放。,结果分析,接着执行Tom的析构函数,此时就会出现问题,即在释放Tom.m_name所指的内存空间时会出现问题,因为这段内存空间在Jim的析构函数中已经释放过了。 出现这种原因的根本在于“浅拷贝”,所以需要定义自己的构造函数。,深拷贝,接下来看Example 3,在该例子中执行深拷贝。,Cperson.h,#ifndef _CPE
7、RSON_H #define _CPERSON_Hclass Cperson public:Cperson(int age,char *name);Cperson(Cperson #endif,Cperson.cpp,#include“Cperson.h“ #include #includeCperson:Cperson(int age,char *name) m_name = new charstrlen(name) + 1;if(m_name != NULL)strcpy(m_name,name);m_age = age;coutm_name“的构造函数“endl; ,Cperson.cp
8、p,Cperson:Cperson(Cperson ,Cperson.cpp,Cperson:Cperson() cout“析构姓名:“m_nameendl;if(m_name != NULL)delete m_name; void Cperson:Print(void) cout“My age is “m_age“,My name is “m_nameendl; ,Main.cpp,#include“Cperson.h“ #includevoid main(void) Cperson Tom(10,“Tom“);Tom.Print();Cperson Jim(Tom);Jim.Print(); ,结果分析,结果分析,可以看到,自己定义了拷贝构造函数后,就没有问题了,浅拷贝和深拷贝,深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。 在实际中应该避免浅拷贝。,