What functions does c++ compiler write for your class silently?答案是:
- Default Constructor
- Destructor
- Copy Constructor
- Copy Assignment Operator
不過應該有不少人心裡嘀咕著"Compiler會產生什麼function關我什麼事?,我會寫class就好~"
其實是有差的。當你寫一個class的時候,如果不考慮這一點,很有可能就替你的client(意指使用你的class的人)設下陷阱。
什麼陷阱?小則leak,大則crash! (其實leak也不算小事啦)
假設你寫了一個很沒有意義的class如下
List 1 - Class TenBytes
class TenBytes { public: TenBytes() {mTenBytes = new char[10];} ~TenBytes() {if (mTenBytes) delete [] mTenBytes;} private: char *mTenBytes; };一切看起來都很正常。在constructor配置了10 bytes,在destructor也有釋放掉,記憶體管理應該沒問題才對。乍看之下的確沒問題,但試想下列情況:
List 2 - Example
TenBytes firstTenBytes; TenBytes secondTenBytes = firstTenBytes;//Copy Constructor is invoked TenBytes thirdTenBytes; thirdTenBytes = firstTenBytes; //Copy Assignment is invoked由於TenBytes這個class並未override copy constructor與copy assignment operator,所以compiler會很雞婆地幫我們產生一個shallow(膚淺) copy constructor與shallow copy assignment operator。所謂的shallow的意思就是只是把該class中member的值直接給了另外一個物件,這在大部分的狀況(如果member都是scalar例如int, float的話)都很合理也沒問題。但如果是pointer的話,就很危險了。
以List 2為例,在執行到line 2時,程式把firstTenBytes的mTenBytes的值複製給secondTenBytes的mTenBytes了,意思就是firstTenBytes的mTenBytes與secondTenBytes的mTenBytes都指向同一個位址了。類似的事情在line 4也發生了,因為程式把firstTenBytes的mTenBytes的值複製給thirdTenBytes的mTenBytes。所以這裡之後會發生兩件事,leak與crash。Leak 是因為thirdTenBytes在constructor配置了10 bytes但mTenBytes所指向的位址因為line 4的assignment給覆蓋掉了。Crash是因為firstTenBytes,secondTenBytes與thirdTenBytes的mTenBytes都指向同一個位址,所以第一個被destruct的物件會釋放掉那10 bytes,當第二個物件被destruct的時候會嘗試去釋放同一個記憶體,所以此時就會crash。
該如何預防呢?
這有兩個選擇:- 乖乖地實作copy constructor與copy assignment operator。
- 把copy constructor與copy assignment operator給隱藏起來(例:List 3)。
class TenBytes { public: TenBytes() {mTenBytes = new char[10];} ~TenBytes() {if (mTenBytes) delete [] mTenBytes;} private: char *mTenBytes; TenBytes(const TenBytes &inTenBytes); TenBytes& operator = (const TenBytes &inTenBytes); };我的習慣是在寫一個class的一開始就把所有method的殼都寫好,大部分在做model class的時候應該都是選1,而在做controller class的時候都選2。因為data model理應可以copy才自然,才合理,而controller的個數通常都是固定的,沒必要有分身。
受教了~
回覆刪除我已經把有些比較不敏感的搬出來惹~
回覆刪除這個觀念是我原本沒有的!!蝦惹辣
回覆刪除這Effective C++有講到,讀書會裡應該會討論到
回覆刪除