本文用Markdown編輯,這里對Markdown的支持不完善,更好的閱讀體驗請移步:我的Markdown文本
C++三大函數:
- 析構函數
- 復制構造函數
- operator=
析構函數
函數模樣:~S()
當一個對象超出作用域或執行delete的時候,析構函數就被調用。
復制構造函數
函數模樣:S(const S& s)
以下情況,復制構造函數均會被調用:
-
聲明的同時初始化:
S s1 = s2; //注意此時雖然出現=,但是不是調用operator=哦 S s1(s2);
-
調用函數時使用按值傳遞(而不是按引用傳遞)
void f(S s); S s1; f(s1);
-
通過值返回對象
S f() { S s1; return s1; }
operator=
函數模樣:const S& operator=(const S& s)
當=應用於兩個已經構造的對象時,就調用復制賦值運算符operator=。
S s1;
s1 = s2; //注意與S s1 = s2; 的區別
注意事項:
-
三大函數不手動實現的時候,會使用默認的版本。比如operator=的默認版本會依次為數據成員復制,如果是基本數據類型自然沒什么問題,但當數據成員含有指針的時候,operator的只會進行
淺復制
,即只是指針本身被復制,而不是指針所指向的內容被復制。見下例。class S { public: int *p; S(int x=0){p=new int(x);} }; void f() { S s1(2), s2; S s3 = s1; s2 = s1; *s1.p=3; cout << *s1.p << ' '<< *s2.p << ' ' << *s3.p << endl;//3 3 3 }
很明顯這不是我們想要的,我們想讓不同的對象的值不互相影響,此時需要實現
深復制
,見下例。class S { public: int *p; S(int x=0){p=new int(x);} S(const S& rhs) { p = new int(*rhs.p); } const S& operator=(const S& rhs) //rhs=right-hand side { if (this != &rhs) //檢查是否復制自身 *p = *rhs.p; return *this; } }; void f() { S s1(2), s2; S s3 = s1; s2 = s1; *s1.p=3; cout << *s1.p << ' '<< *s2.p << ' ' << *s3.p << endl; //3 2 2 }