一個空類時,編譯器會預設產生建構函式,拷貝建構函式,賦值函數,解構函式 一個類如果重寫拷貝建構函式,那麼必須自訂一個建構函式。如下代碼會編譯出錯:error C2512: “B”: 沒有合適的預設建構函式可用
class B{public: B(const B &b) { }};int main(void){ B b; getchar(); return 0;}修正為:
class B{public: B() {} B(const B &b) { }};int main(void){ B b; getchar(); return 0;}
拷貝建構函式和賦值函數的正確寫法(if(this != &b))
class B{public: B(int v) { m_value = v; } B(const B &b) { m_value = b.m_value; } B &operator =(const B &b) { if(this != &b) { m_value = b.m_value; } return *this; }private: int m_value;};
函數傳回值是對象時,要考慮return語句的效率。
B createObj0(void){ return B(0);}B createObj1(void){ B b(0); return b;}createObj0建立一個臨時對象並返回它,編譯器直接把臨時對象建立並初始化在外部儲存單元中,省去了拷貝和析構的過程。createObj1則是先建立b對象,然後拷貝構造把b拷貝到外部儲存單元中去,接著還會析構掉b對象。請對比下列兩組代碼及運行結果:
#include <stdio.h>int g_counter = 0;class B{public: B(void) { m_value = g_counter++; printf("B() m_value=%d\n", m_value); } ~B() { printf("~B() m_value=%d\n", m_value); } B(const B &a) { m_value = g_counter++; printf("B(const B &a) m_value=%d\n", m_value); } B &operator=(const B&a) { printf("B &operator=(const B&a)\n"); return *this; }private: int m_value;};B createObj0(const B b){ B bb(b); return bb;}B createObj1(const B b){ return B(b);}int main(void){ B __b; B _b = createObj0(__b);return 0;}運行結果:
#include <stdio.h>int g_counter = 0;class B{public: B(void) { m_value = g_counter++; printf("B() m_value=%d\n", m_value); } ~B() { printf("~B() m_value=%d\n", m_value); } B(const B &a) { m_value = g_counter++; printf("B(const B &a) m_value=%d\n", m_value); } B &operator=(const B&a) { printf("B &operator=(const B&a)\n"); return *this; }private: int m_value;};B createObj0(const B b){ B bb(b); return bb;}B createObj1(const B b){ return B(b);}int main(void){ B __b; B _b = createObj1(__b);return 0;}
運行結果: