题目:
如下为类型CMyString的声明,请为该类型添加赋值运算法函数。
class CMyString {
public:
CMyString(char* pData = NULL);
CMyString(const CMyString& str);
~CMyString(void);
private:
char* m_pData;
};
实现:
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;
}
四个注意的点:
返回值类型:返回值类型是声明类型的引用,并在函数结束前返回实例自身的引用(*this)。原因:只有返回引用才能进行连续的赋值操作,如str1 = str2 = str3。
传入参数类型:传入参数的类型是常量的引用。原因:传入的是实例时,在形参到实参转化的时候会调用一次复制构造函数,这就造成无所谓的消耗。其次由于赋值运算不改变实例的状态,传入的引用参数上加const关键字。
释放自身的内存:在分配内存之前释放自身已有的内存,防止出现内存的泄漏。
传入参数和当前实例是否是同一个实例的判断:如果是同一个实例直接返回,不进行赋值操作,如果不判断直接赋值,在是同一个实例的情况下,释放实例自身内存的时候,传入参数的实参内存也被释放了,找不到要赋值的内容,出现很大的问题。
改进:
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;
}
在分配内存之前先delete释放了m_pData的内存,在申请分配内存,如果此时的内存不足时会导致new char抛出异常,m_pData变成一个空指针,容易导致程序崩溃。
改进的优点在于:在delete之前先创建了一个临时的实例,这样交换指针所指的位置,而指向原来实例的局部变量会在if之外(作用域之外)自动调用strTemp的析构函数,把之前的实例所占用的内存释放掉。