題目:如下爲類型CMyString的聲明,請爲該類型添加賦值運算符函數。
class CMyString
{
private:
char * m_pData;
public:
CMyString(char *pData = NULL);
CMyString(const CMyString &str);
~CMyString(void);
};
這裏要注意一下幾點:
- 是否把返回值的類型聲明爲該類型的引用,並在函數結束前返回實例自身的引用(*this)。只有返回一個引用,纔可以允許連續賦值。
- 是否把傳入的形參的類型聲明爲常量引用。如果傳入的參數不是引用而是實例,那麼從形參到實參會調用一次複製構造函數。
- 是否釋放實例自身已有的內存。如果忘記在重新分配內存之前釋放自身已有的空間,程序將出現內存泄露。
- 是否判斷傳入的參數和當前實例(*this)是不是同一個實例。
經典解法:
CMyString& CMyString::operator = (const CMyString *str)
{
if(this == &str)
return *this;
delete []m_pData;
m_pData = NULL;
m_pData = new char[strlen(str.m_pData) + 1];
strcpy(m_pData, str.m_pData);
return *this;
}
考慮異常安全性的解法:
前面的函數中,我們在分配內存之前先用了delete釋放了實例m_pData的內存。如果此時內存不足導致new char拋出異常,m_pData將是一個空指針,CMyString的實例不再保持有效的狀態,這就違背了異常安全性原則。
辦法是先創建一個臨時實例,在交換臨時實錄和原來的實例。
CMyString& CMyString::operator = (const CMyString *str)
{
if(this != &str)
{
CMyString strTemp(str);
char *pTemp = strTemp.m_pData;
strTemp.m_pData = m_pData;
m_pData = pTemp;
}
return *this;
}
由於strTemp是一個局部變量,程序運行到if的外面即除了改變量的作用域,就會自動調用strTemp的析構函數,把strTemp.m_pData所指向的內存釋放掉。