題目:如下為類型CMyString的聲明像捶,請為該類型添加賦值運(yùn)算符函數(shù)
#include "stdafx.h"#includeclass CMyString
{
public:
CMyString(char* pData = NULL);
CMyString(const CMyString& str);
~CMyString(void);
CMyString& operator = (const CMyString& str);
void Print();
private:
char* m_pData;
};
CMyString::CMyString(char *pData)
{
if(pData == NULL)
{
m_pData = new char[1];
m_pData[0] = '\0';
}
else
{
int length = strlen(pData);
m_pData = new char[length + 1];
strcpy(m_pData, pData);
}
}
CMyString::CMyString(const CMyString &str)
{
int length = strlen(str.m_pData);
m_pData = new char[length + 1];
strcpy(m_pData, str.m_pData);
}
CMyString::~CMyString()
{
delete[] m_pData;
}
該類題型一定要注意以下幾點(diǎn):
1.是否把返回值類型聲明為該類型的引用。
只有返回一個引用媳纬,才可以連續(xù)賦值球匕。
2.是否把傳入的參數(shù)的類型聲明為常量引用纹磺。
把參數(shù)類型聲明為常量引用,可以避免從形參到實(shí)參所調(diào)用構(gòu)造函數(shù)這一無謂的消耗谐丢。(別忘了const)
3.是否釋放實(shí)例已有的內(nèi)存
如果忘記,則當(dāng)指針指向其他內(nèi)存時蚓让,會出現(xiàn)內(nèi)存泄漏
4.是否判斷傳入的參數(shù)和當(dāng)前的實(shí)例是不是同一實(shí)例
如果*this和傳入的參數(shù)是同一實(shí)例乾忱,則不能繼續(xù),因?yàn)槿绻^續(xù)的話历极,先釋放實(shí)例已有的內(nèi)存窄瘟,再申請新的內(nèi)存,這樣會釋放自身的內(nèi)存趟卸,傳入的參數(shù)的內(nèi)存也被釋放了蹄葱,因此再也找不到需要賦值的內(nèi)容了。
根據(jù)以上幾點(diǎn)锄列,寫出這樣的代碼:
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;
}
但是图云,這樣并不完美,因?yàn)槭窍柔尫诺膬?nèi)存邻邮,后申請的空間竣况,因此如果當(dāng)內(nèi)存不足的時候,實(shí)例自身的內(nèi)存會被釋放筒严,同時又沒有新的值給它丹泉,m_pData將是一個空指針,這樣程序的內(nèi)存容易崩潰鸭蛙。
因此有如下解決方法:一個簡單的做法是先用new分配摹恨,再釋放已有內(nèi)存,這樣只有在分配成功之后再釋放原來的內(nèi)存娶视,更好的方法是借助一個臨時變量晒哄,再交換臨時實(shí)例和原來的實(shí)例。
CMyString& CMyString::operator = (const CMyString& str)
{
if (this!=&str) {
CMyString strTemp=CMyString(str);
char *pTemp=strTemp.m_pData;
strTemp.m_pData=m_pData;
m_pData=pTemp;
}
return *this;
}
如果對重點(diǎn)標(biāo)注的代碼表示不理解,那么請看下面:
m_pData為實(shí)例自身的內(nèi)存揩晴,而strTemp為一個局部變量勋陪,當(dāng)程序出了if之后,就會釋放掉strTemp硫兰,這樣原來m_pData的內(nèi)存就會釋放掉诅愚,否則會出現(xiàn)內(nèi)存泄漏。