拷貝構造函數在下面三種狀況下被調用:函數
賦值運算只有一種狀況會被調用:this
代碼:spa
1 #include <stdlib.h> 2 #include <string> 3 4 /*** 5 * @author:zanzan101 6 */ 7 8 inline void P(const char* str) 9 { 10 printf("%s\n", str); 11 } 12 13 class A 14 { 15 private: 16 int _data; 17 char* _name; 18 public: 19 A(): _name(0) 20 { 21 P("調用構造函數"); 22 } 23 24 // 拷貝構造函數 25 // 不管構造函數仍是拷貝構造函數,都要處理好對於指針的初始化,通常,應該一開始就對指針賦值爲0,後面再進一步賦值 26 // 對象的產生,究其根源只有兩個途徑:構造和拷貝構造,賦值運算的右值也是來自這兩種途徑 27 A(A& a) 28 { 29 P("調用拷貝構造函數"); 30 _name = 0; 31 _data = a._data; 32 if(a._name) 33 { 34 _name = new char[strlen(a._name)+1]; 35 strcpy(_name, a._name); 36 } 37 } 38 39 // 賦值運算符 40 // 注意:返回值類型設爲A&是爲了實現a=b=c、(a=b)=c等操做 41 A& operator= (A& a) 42 { 43 P("調用賦值運算符"); 44 45 if(this == &a) 46 return *this; 47 48 // 調用賦值運算的對象,必然已經經歷過了構造或者拷貝構造 49 // 所以,合理的設計構造和拷貝構造函數,會使_name爲0或者其餘有效值,不會出現0xCCCCCCCC的非法狀況 50 if(_name) 51 delete _name; 52 53 _data = a._data; 54 55 if(!a._name) 56 _name = 0; 57 else 58 { 59 _name = new char[strlen(a._name)+1]; 60 strcpy(_name, a._name); 61 } 62 return *this; 63 } 64 }; 65 66 void foo(A a) 67 { 68 return; 69 } 70 int _tmain(int argc, _TCHAR* argv[]) 71 { 72 P(">> 聲明對象,但不初始化時:"); 73 A a; 74 75 P(">> 聲明對象同時用對象進行初始化時:"); 76 A b = a; 77 78 P(">> 先聲明對象:"); 79 A c; 80 P(">> 再對對象進行賦值時:"); 81 c = a; 82 83 P(">> 使用拷貝構造函數初始化時:"); 84 A d(a); 85 86 P(">> 在函數調用傳入形式參數時:"); 87 foo(a); 88 89 90 system("pause"); 91 return 0; 92 }
輸出:設計
>> 聲明對象,但不初始化時: 調用構造函數 >> 聲明對象同時用對象進行初始化時: 調用拷貝構造函數 >> 先聲明對象: 調用構造函數 >> 再對對象進行賦值時: 調用賦值運算符 >> 使用拷貝構造函數初始化時: 調用拷貝構造函數 >> 在函數調用傳入形式參數時: 調用拷貝構造函數 請按任意鍵繼續. . .