&emsp
在c++中, 建構函式,拷貝建構函式,析構函式和賦值函式(賦值運算子過載)是最基本不過的需要掌握的知識。 但是如果我問你「拷貝建構函式的引數為什麼必須使用引用型別?」這個問題, 或許你會回答為了減少一次記憶體拷貝? 很慚愧,思索一下以後,發現這個答案是不對的。
先從乙個小例子開始:(自己測試一下自己看看這個程式的輸出是什麼?
#include
class cexample
cexample(const cexample & ex) //拷貝建構函式
cexample& operator = (const cexample &ex)//賦值函式(賦值運算子過載)
void mytestfunc(cexample ex)
};int main()
輸出結果:
constructor with argument //cexample aaa(2);第乙個輸出:constructor with argument //cexample bbb(3);
assignment operator //bbb = aaa;
copy constructor //cexample ccc = aaa;
copy constructor // bbb.mytestfunc(aaa);
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;那麼又會觸發拷貝建構函式,就這下永遠的遞迴下去。
拷貝建構函式的引數使用引用型別不是為了減少一次記憶體拷貝, 而是避免拷貝建構函式無限制的遞迴下去。所以, 拷貝建構函式是必須要帶引用型別的引數的, 而且這也是編譯器強制性要求的
**:
拷貝建構函式的引數為什麼必須是引用?
1 include2 include 3using namespace std 4class foo5 13 foo foo f ss f.ss 1417 foo operator const foo f1 1822 void test foo f2 2326 27 28int main 29 如果...
拷貝建構函式的引數為什麼必須使用引用型別
在c 中,建構函式,拷貝建構函式,析構函式和賦值函式 賦值運算子過載 是最基本不過的需要掌握的知識。但是如果我問你 拷貝建構函式的引數為什麼必須使用引用型別?這個問題,你會怎麼回答?或許你會回答為了減少一次記憶體拷貝?很慚愧的是,我的第一感覺也是這麼回答。不好還好,我有理性這個好品質。思索一下以後,...
拷貝建構函式的引數為什麼必須使用引用型別
在c 中,建構函式,拷貝建構函式,析構函式和賦值函式 賦值運算子過載 是最基本不過的需要掌握的知識。但是如果我問你 拷貝建構函式的引數為什麼必須使用引用型別?這個問題,你會怎麼回答?或許你會回答為了減少一次記憶體拷貝?很慚愧的是,我的第一感覺也是這麼回答。不好還好,我有理性這個好品質。思索一下以後,...