What functions does
c++ compiler write for your class silently?
答案是:
1. Default
Constructor
2. Destructor
3. Copy Constructor
4. Copy Assignment
Operator
其實是有差的。當你寫一個class的時候,如果不考慮這一點,很有可能就替你的client(意指使用你的class的人)設下陷阱。小則leak,大則crash!
假設你寫了一個很沒有意義的class如下
example 1
class TenBytes
{
public:
TenBytes()
{mTenBytes = new char[10];}
~TenBytes() {if (mTenBytes)
delete [] mTenBytes;}
private:
char *mTenBytes;
};
一切看起來都很正常。在constructor配置了10 bytes,在destructor也有釋放掉,記憶體管理應該沒問題才對。乍看之下的確沒問題,但試想下列情況:
example 2
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的話,就很危險了。
以第二個example,在執行到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。
該如何預防呢?
這有兩個選擇:
1. 乖乖地實作copy constructor與copy assignment operator。(ex3)
2. 把copy constructor與copy assignment
operator給隱藏起來。(ex4)
example3
class TenBytes
{
public:
TenBytes() {mTenBytes = new char[10];}
~TenBytes() {if (mTenBytes) delete [] mTenBytes;}
TenBytes(const TenBytes &inTenBytes);
TenBytes& operator = (const TenBytes
&inTenBytes);
private:
char *mTenBytes;
};
example4
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的個數通常都是固定的,沒必要有分身。
沒有留言:
張貼留言