賦值運算符函數

題目:如下爲類型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所指向的內存釋放掉。


發佈了57 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章