在《
工作中發現的 》中,提到析構函數可以自己調用,并用一個例子編譯、運行證明了。
現在有個問題,除了知道“析構函數
可以自己調用”外,那么什么時候
必須顯式調用析構函數?
先看一段現實生活中的代碼吧,mfc源碼中:
BOOL CStatusBar::AllocElements(int nElements, int cbElement)
{
// destruct old elements
AFX_STATUSPANE* pSBP = _GetPanePtr(0);
for (int i = 0; i < m_nCount; i++)
{
pSBP->strText.~CString(); //注意看這里
++pSBP;
}
// allocate new elements
if (!CControlBar::AllocElements(nElements, cbElement))
return FALSE;
// construct new elements
pSBP = _GetPanePtr(0);
for (i = 0; i < m_nCount; i++)
{
memcpy(&pSBP->strText, &afxEmptyString, sizeof(CString));
++pSBP;
}
return TRUE;
}
在上面的代碼中,就有顯式調用CString的析構函數的代碼。cool。
因為還調用了
CControlBar::AllocElements(),上面的代碼不是很明顯,我把CControlBar::AllocElements簡化一下后:
BOOL CStatusBar::AllocElements(int nElements, int cbElement)
{
// destruct old elements
AFX_STATUSPANE* pSBP = _GetPanePtr(0);
for (int i = 0; i < m_nCount; i++)
{
pSBP->strText.~CString(); //注意看這里
++pSBP;
}
// allocate new elements
//if (!CControlBar::AllocElements(nElements, cbElement))
// return FALSE;
//簡化后的代碼,實際運行肯定有問題,但是關鍵東西出來了
free(pSBP);//注意這里調用的是free
pSBP = calloc(nElements, cbElement);
// construct new elements
pSBP = _GetPanePtr(0); //根據mfc的代碼,可以理解這里的pSBP和前面的pSBP還是同一個地址
for (i = 0; i < m_nCount; i++)
{
memcpy(&pSBP->strText, &afxEmptyString, sizeof(CString));
++pSBP;
}
return TRUE;
}
這個時候,如果注意到我特別注釋的free函數調用,可能已經意識到了為什么要顯式調用析構函數了。
如果還沒有,那么可以問自己一個面試常規問題:delete和free有什么區別?答:delete會使析構函數被調用。
或者反過來說,
free沒有調用析構函數,那么怎么辦?所以你必須自己顯示調用析構函數。

上面的這個例子可以這樣抽象下,現在需要free掉一塊內存,而那塊內存中,還有一個類,類里面還有指針,(這里是CString)需要在析構函數中釋放內存。因為用的是free,所以那個類的析構函數不會自動被調用,這個時候,就
必須顯式調用那個類的析構函數。
這個是不是很偏的問題呢?遇到了就看看,沒有遇到過,也不會影響日常工作,哈。
另外繼續問個面試問題,new和calloc的區別?哈,構造的函數的調用啊
所以,上面的代碼用的calloc,就必須顯示調用構造函數啊,在哪里呢?就是
memcpy(&pSBP->strText, &afxEmptyString, sizeof(CString));
和CString的構造函數比較下:
_AFX_INLINE CString::CString()
{ m_pchData = afxEmptyString.m_pchData; }
但是,為什么不就直接調用構造函數呢?我也不知道。詳見下面的評論。(糾正了我的一個錯誤)
不過,下面的代碼
CString aStr;
CString* pStr = &aStr ;
pStr->CString();
是編譯不過的。
