题目:为如下类型CMyString的声明,请为该类型添加赋值运算符函数。
class CMyString
{
public:
CMyString(char* pData = null);
CMyString(const& CMyString str);
~CMyString(void);
private:
char* m_pData;
};
需要注意的点:
- 函数返回值为该类的引用,如果不是则该函数不能用于连续赋值
- 函数的参数要声明为常量引用,如果传入的不是引用而是实例则会在形参到实参复制时会调用一次赋值构造函数,造成不必要的浪费
- 是否释放了实例本身已有的内存,如果没有释放在分配新内存的时候将会出现内存泄露
- 判断传入的参数和实例自身是不是同一个,如果是同一个实例则会在释放内存的时候将自己释放掉
综上:
CMyString& CMyString::operator=(const CMyString& str) //考点2
{
if(this == &str) //第4个考点
return *this;
delete []m_pData; //考点3
m_pData = nullptr;
m_pData = new char[strlen(str.m_pData) + 1];
strcp(m_pData, str.m_pData);
return *this; //考点1
考虑到安全性:
上面的例子中先删掉了m_pData然后再进行重新分配内存。考虑一点:如果在删除之后没有新的足够的内存供分配,此时会因为内存不足抛出异常。所以应该在删除前先new创建新的内存空间,如果内存不足也不会删去原有的内存。
改进版:
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,由于它是一个局部变量,在程序运行到函数外是就会将其释放掉。而且strTemp.m_pData指向的是原来实例中m_pData,这就相当于自动释放了内存。