#include <iostream> using namespace std; class CExample { public: CExample(int x) :m_nTest(x) //帶參數構造函數 { cout<< "constructor with argument."<<endl; } CExample(const CExample & ex) //拷貝構造函數 { m_nTest = ex.m_nTest; cout << "copy constructor."<<endl; } CExample& operator = (const CExample &ex)//賦值函數(賦值運算符重載) { cout << "assignment operator." << endl; m_nTest = ex.m_nTest; return *this; } void myTestFunc(CExample ex) { } private: int m_nTest; }; int main() { CExample aaa(2); CExample bbb(3); bbb = aaa; CExample ccc = aaa; bbb.myTestFunc(aaa); system("pause"); return 0; }
第一個輸出: constructor with argument. //CExample aaa(2);html
這裏建立了變量aaa,在建立的同時還帶有參數2,那就調用帶參數的構造函數ios
第二個輸出:constructor with argument. //CExample bbb(3);小程序
分析同第一個安全
第三個輸出:assignment operator. //bbb = aaa;函數
bbb以前已經建立了,因此這個不會調用構造函數,而只是將aaa賦值給bbb,因此調用賦值函數
第四個輸出:copy constructor. //CExample ccc = aaa;this
這個和上一個的區別就在於:bbb以前已經建立過了,而這裏的ccc是在這條語句才建立的,因此這裏是在建立ccc的同時將aaa賦值給ccc,因此這句調用的確定是構造函數,又由於須要將aaa賦值給ccc,因此調用的是拷貝構造函數。spa
第五個輸出:copy constructor. // bbb.myTestFunc(aaa);
這裏是調用了一個本身寫的myTestFunc函數,其中這個函數中的參數沒有采用引用,那就是值傳遞的方式。就是編譯器先建立一個類型爲CExample名稱爲ex的對象,而後將aaa的值傳遞給ex(值傳遞方式的特性),將至關於要執行一條CExample ex = aaa的語句。經第四個輸出的分析可知,這須要調用拷貝構造函數。因此輸出copy constrctor。.net
【錯誤答案】我的第一反應:爲了減小一次內存拷貝。htm
【正確答案】由上節的第五個輸出分析可知,在執行bbb.myTestFunc(aaa);時,其實會調用拷貝構造函數。若是咱們的拷貝構造函數的參數不是引用,那麼在bbb.myTestFunc(aaa);時,調用CExample ex = aaa;,又由於ex以前沒有被建立,因此又須要調用拷貝構造函數,故而又執行CExample ex = aaa;,就這樣永遠的遞歸調用下去了。對象
因此, 拷貝構造函數是必需要帶引用類型的參數的, 並且這也是編譯器強制性要求的。
【正確答案】若是在函數中不會改變引用類型參數的值,加不加const的效果是同樣的。並且不加const,編譯器也不會報錯。可是爲了整個程序的安全,仍是加上const,防止對引用類型參數值的意外修改。
——若有不對的地方,很是歡迎給予指導!
——【感謝】資料來源於https://www.cnblogs.com/engraver-lxw/p/7580403.html
——【感謝】資料來源於http://blog.csdn.net/tunsanty/article/details/4264738
——【感謝】資料來源於http://blog.csdn.net/sinat_36053757/article/details/70597567