1. 空類
1.1 空類默認哪六個成員函數。
1 class Empty
2 {
3 public:
4 Empty(); //缺省構造函數 Empty e;
5 Empty( const Empty& ); //拷貝構造函數 Empty e2(e1);
6 ~Empty(); //析構函數
7 Empty& operator=( const Empty& ); //賦值運算符 Empty e2 = e1;
8 Empty* operator&(); //取址運算符 &e
9 const Empty* operator&() const; //取址運算符const &e
10 };
?
1.2 空類的sizeof()=1
每個實例在內存中都有一個獨一無二的地址,為了達到這個目的,編譯器往往會給一個空類隱含的加一個字節,這樣空類在實例化后在內存得到了獨一無二的地址。
2. string類
以下四個函數,是C++編譯器會自動加入的四個函數。
1 class MyString 2 { 3 public: 4 MyString(const char *str = NULL);//默認參數,不傳遞的該參數的時候發揮作用。 5 MyString(const MyString &other); 6 MyString& operator=(const MyString &other); 7 ~MyString(); 8 private: 9 char *m_data; 10 }; 11 MyString::~MyString() 12 { 13 delete [] m_data; 14 } 15 MyString::MyString(const char *str) 16 { 17 if(NULL == str) 18 { cout<<"調用普通構造函數1"<<endl; 19 m_data = new char[1]; 20 *m_data = '\0'; 21 } 22 else 23 { 24 cout<<"調用普通構造函數2"<<endl; 25 size_t length = strlen(str); 26 m_data = new char[length+1]; 27 strcpy(m_data,str); 28 } 29 } 30 MyString::MyString(const MyString &other) 31 { cout<<"調用拷貝構造函數"<<endl; 32 size_t length = strlen(other.m_data); 33 m_data = new char[length+1]; 34 strcpy(m_data,other.m_data); 35 } 36 MyString& MyString::operator =(const MyString &other) 37 { 38 cout<<"調用賦值函數"<<endl; 39 //檢查自賦值 40 if(this == &other) 41 return *this; 42 //釋放原有的內存資源 43 delete [] m_data; 44 int length = strlen(other.m_data); 45 m_data = new char[length+1]; 46 strcpy(m_data,other.m_data); 47 return *this; 48 } 49 int _tmain(int argc, _TCHAR* argv[]) 50 { 51 MyString s0;//"調用普通構造函數1" 52 MyString s1 = "hi";//"調用普通構造函數2" 53 MyString s2("hi");//"調用普通構造函數2" 54 55 MyString s3 = s1;//"調用拷貝構造函數"上述實現為深拷貝。 56 MyString s4(s2);//"調用拷貝構造函數" 57 s4 = "hello!";//將"hello!"傳入賦值函數形參時,要調用普通構造函數2;接著調用賦值函數。 58 s4 = s3;//"調用賦值函數" 59 return 0; 60 }
總結:僅定義對象或者傳遞對象的時候調用構造函數。
說明:拷貝構造函數必須傳引用。調用拷貝構造函數如果傳值,編譯器會新開辟一段棧內存,建立此對象的臨時拷貝,而建立臨時拷貝又需要值傳遞調用拷貝構造函數,如此
進入死循環,直至內存耗盡死機。而傳引用則無需新開辟內存空間,無需調用構造函數,形參對象只是另一個對象的別名。
?