关于c++深拷贝与浅拷贝
首先看一段代码:
1 #include<iostream> 2 #include<cstring> 3 #include<malloc.h> 4 using namespace std; 5 6 class Teacher{ 7 public: 8 Teacher(int id,char *name){ 9 m_id=id; 10 11 m_name=(char*)malloc(strlen(name)+1);//由于显示析构函数中free内存空间,因而必须malloc 12 strcpy(m_name,name); 13 } 14 15 void Print(){ 16 cout<<"id="<<m_id<<" name="<<m_name<<endl; 17 } 18 19 ~Teacher(){/*显示析构函数*/ 20 cout<<"Teacher()..."<<endl; 21 if(m_name!=NULL){ 22 free(m_name); 23 m_name=NULL; 24 } 25 } 26 private: 27 int m_id; 28 char *m_name; 29 }; 30 31 int main(){ 32 Teacher t1(1,"zhangsan"); 33 t1.Print(); 34 35 return 0; 36 }
浅谈析构函数特点:
1.函数名是在类名前加上~,无参数且无返回值。
2.一个类只能有且有一个析构函数,如果没有显式的定义,系统会生成一个缺省的析构函数(合成析构函数)。
3.析构函数不能重载。每有一次构造函数的调用就会有一次析构函数的调用。
1 #include<iostream> 2 #include<cstring> 3 #include<malloc.h> 4 using namespace std; 5 6 class Teacher{ 7 public: 8 Teacher(int id,char *name){ 9 cout<<"Teacher(int,char*)..."<<endl; 10 m_id=id; 11 12 int len=strlen(name); 13 m_name=(char*)malloc(len+1);//由于显示析构函数中free内存空间,因而必须malloc 14 strcpy(m_name,name); 15 } 16 /*默认拷贝构造函数,浅拷贝!!!*/ 17 Teacher(const Teacher& another){ 18 m_id=another.m_id; 19 m_name=another.m_name; 20 } 21 void Print(){ 22 cout<<"id="<<m_id<<" name="<<m_name<<endl; 23 } 24 25 ~Teacher(){/*显示析构函数*/ 26 cout<<"Teacher()..."<<endl; 27 if(m_name!=NULL){ 28 free(m_name); 29 m_name=NULL; 30 } 31 } 32 private: 33 int m_id; 34 char *m_name; 35 }; 36 37 void test(){ 38 Teacher t1(1,"xiaoming"); 39 t1.Print(); 40 41 Teacher t2(t1);//t2的默认拷贝构造 42 t2.Print(); 43 } 44 45 int main(){ 46 test(); 47 48 return 0; 49 }
【浅拷贝】是增加了一个指针,指向原来已经存在的内存。
而【深拷贝】是增加了一个指针,并新开辟了一块空间,让指针指向这块新开辟的空间
在test函数结束时,t1和t2都会走一遍析构函数,释放内存空间,t2后执行,因而先走析构函数,将name的内存空间释放掉,当t1走析构函数时,会再次进行m_name的内存空间释放,但由于这块内存空间在t2走析构函数时已经被释放掉了,所以在这里会引发段错误!!!,这也就是浅拷贝的危害。。。
为了避免浅拷贝引发的段错误,因而我们需要进行深拷贝,重写拷贝构造函数
1 #include<iostream> 2 #include<cstring> 3 #include<malloc.h> 4 using namespace std; 5 6 class Teacher{ 7 public: 8 Teacher(int id,char *name){ 9 cout<<"Teacher(int,char*)..."<<endl; 10 m_id=id; 11 12 int len=strlen(name); 13 m_name=(char*)malloc(len+1);//由于显示析构函数中free内存空间,因而必须malloc 14 strcpy(m_name,name); 15 } 16 /*重写拷贝构造函数,深拷贝*/ 17 Teacher(const Teacher& another){ 18 m_id=another.m_id; 19 //深拷贝// 20 int len=strlen(another.m_name); 21 m_name=(char*)malloc(len+1); 22 strcpy(m_name,another.m_name); 23 } 24 void Print(){ 25 cout<<"id="<<m_id<<" name="<<m_name<<endl; 26 } 27 28 ~Teacher(){/*显示析构函数*/ 29 cout<<"Teacher()..."<<endl; 30 if(m_name!=NULL){ 31 free(m_name); 32 m_name=NULL; 33 } 34 } 35 private: 36 int m_id; 37 char *m_name; 38 }; 39 40 void test(){ 41 Teacher t1(1,"xiaoming"); 42 t1.Print(); 43 44 Teacher t2(t1);//t2的默认拷贝构造 45 t2.Print(); 46 } 47 48 int main(){ 49 test(); 50 51 return 0; 52 }
有些目标看似很遥远,但只要付出足够多的努力,这一切总有可能实现!