给出如下CMyString声明,添加赋值运算符函数:
class CMyString
{
public:
CMyString(char* pData = NULL);
CMyString(const CMyString& str);
~CMyString(void);
private:
char* m_pData;
};
定义一个赋值运算符函数时,需要注意如下几点:
- 返回值的类型为该类型的引用;函数返回自身实例的引用(*this);只有返回一个引用,才允许连续赋值(str1 = str2 = str3);
- 形参为常量引用;传值会导致调用一次拷贝构造函数;
- 释放之前内存,内存泄漏;
- 传入的参数是否为自身;为自身则直接返回;如果事先不判断,则可能会导致释放了自身的内存;
代码如下:
CMyString& CMyString::operator=(const CMyString& other)
{
if (this == &other)
{
return *this;
}
if (m_pData)
{
delete [] m_pData;
m_pData = NULL;
}
m_pData = new char[strlen(other.m_pData) + 1];
strcpy(m_pData, other.m_pData);
return *this;
}
进一步考察,我们在析构函数中同样显式的释放了 m_pData的内存,但是如果我们添加一个新的指针变量,则需要在多处同时添加 delete操作,这通常会产生安全隐患;
可以利用析构函数释放所有的内存:
CMyString& CMyString::operator=(const CMyString& other)
{
if (this != &other)
{
CMyString temp(other);
char* pTemp = temp.m_pData;
temp.m_pData = m_pData; // 将临时变量的数据域指向当前实例的数据域
m_pData = pTemp;
}
return *this;
}
将临时变量的数据域指向当前实例的数据,由于 temp是临时变量,出了 if作用域之后调用虚构函数,吧 temp.m_pData所指的内存释放掉;由于此时 temp.m_pData所指的内存就是当前实例之前的 m_pData,相当于释放了实例的内存;
参考:
http://zhedahht.blog.163.com/blog/static/25411174200741543224391/