部分轉載自
#include<iostream>using namespace std;class CExample{PRivate: int m_nTest;public: CExample(int x) : m_nTest(x) //帶參數構造函數 { cout << "constructor with argument"<<endl; } // 拷貝構造函數,參數中的const不是嚴格必須的,但引用符號是必須的 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) { }};int main(void){ CExample aaa(2); CExample bbb(3); bbb = aaa; CExample ccc = aaa; bbb.myTestFunc(aaa); return 0; }如果你能一眼看出就是這個結果的話, 恭喜你,可以站起來扭扭屁股,不用再往下看了。如果你的結果和輸出結果有誤差, 那拜托你謙虛的看完。第一個輸出: constructor with argument // CExample aaa(2);如果你不理解的話, 找個人把你拖出去痛打一頓,然后嘴里還喊著“我是二師兄,我是二師兄.......”第二個輸出:constructor with argument // CExample bbb(3);分析同第一個第三個輸出: assignment operator // bbb = aaa;第四個輸出: copy constructor // CExample ccc = aaa;這兩個得放到一塊說。 肯定會有人問為什么兩個不一致。原因是, bbb對象已經實例化了,不需要構造,此時只是將aaa賦值給bbb,只會調用賦值函數,就這么簡單,還不懂的話,撞墻去! 但是ccc還沒有實例化,因此調用的是拷貝構造函數,構造出ccc,而不是賦值函數,還不懂的話,我撞墻去!!第五個輸出: copy constructor // bbb.myTestFunc(aaa);實際上是aaa作為參數傳遞給bbb.myTestFunc(CExample ex), 即CExample ex = aaa;和第四個一致的, 所以還是拷貝構造函數,而不是賦值函數, 如果仍然不懂, 我的頭剛才已經流血了,不要再讓我撞了,你就自己使勁的再裝一次吧。通過這個例子, 我們來分析一下為什么拷貝構造函數的參數只能使用引用類型。看第四個輸出: copy constructor // CExample ccc = aaa;構造ccc,實質上是ccc.CExample(aaa); 我們假如拷貝構造函數參數不是引用類型的話, 那么將使得 ccc.CExample(aaa)變成aaa傳值給ccc.CExample(CExample ex),即CExample ex = aaa,因為 ex 沒有被初始化, 所以 CExample ex = aaa 繼續調用拷貝構造函數,接下來的是構造ex,也就是 ex.CExample(aaa),必然又會有aaa傳給CExample(CExample ex), 即 CExample ex = aaa;那么又會觸發拷貝構造函數,就這下永遠的遞歸下去。所以繞了那么大的彎子,就是想說明拷貝構造函數的參數使用引用類型不是為了減少一次內存拷貝, 而是避免拷貝構造函數無限制的遞歸下去。附帶說明,在下面幾種情況下會調用拷貝構造函數:a、顯式或隱式地用同類型的一個對象來初始化另外一個對象。如上例中,用對象c初始化d;b、作為實參(argument)傳遞給一個函數。如CClass(const CClass c_class)中,就會調用CClass的拷貝構造函數;c、在函數體內返回一個對象時,也會調用返回值類型的拷貝構造函數;d、初始化序列容器中的元素時。比如 vector<string> svec(5),string的缺省構造函數和拷貝構造函數都會被調用;e、用列表的方式初始化數組元素時。string a[] = {string(“hello”), string(“world”)}; 會調用string的拷貝構造函數。如果在沒有顯式聲明構造函數的情況下,編譯器都會為一個類合成一個缺省的構造函數。如果在一個類中聲明了一個構造函數,那么就會阻止編譯器為該類合成缺省的構造函數。和構造函數不同的是,即便定義了其他構造函數(但沒有定義拷貝構造函數),編譯器總是會為我們合成一個拷貝構造函數。
新聞熱點
疑難解答
圖片精選