1. 程式人生 > >關於c++深拷貝與淺拷貝

關於c++深拷貝與淺拷貝

using 釋放 ios ngs not 這也 void 圖片 指向

首先看一段代碼:

 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 }

關於c++深拷貝與淺拷貝