面试题1: 赋值运算符函数
题目:如下类型为CMyString的声明,请为该类型添加赋值运算符函数。
class CMyString
{
public:
CMyString(char *pData = nullptr);
CMyString(const CMyString &str);//常对象
~CMyString(void);
private:
char *m_pData;
};
赋值运算符(=)函数:
-
返回值类型:该类类型的引用。返回(*this),这样可以连续赋值。
-
函数参数声明为常量引用,如果是传值(实例),从形参到实参会调用一次复制构造函数。
-
释放实例自身已有的内存
-
判断传入的参数和当前实例(*this)是否为同一个实例。
1.基本做法
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;
}
2.考虑异常安全性(1)
当内存不够时,new char会抛出异常,分配内存失败,m_pData将是一个空指针,这样容易导致程序崩溃。
解决办法:先用new分配内存,只有当分配成功,再delete释放已有的内容。
CMyString& CMyString::operator =(const CMyString& str){
if(this == &str)//根据实例地址判断是不是同一个实例
return *this;//返回实例 实例引用。
char *temp = NULL;//指向新分配的内存
temp = new char[strlen(str.m_pData) + 1];//根据新的内容分配内存。
if(temp == NULL)//如果分配失败
return *this;
//分配成功
delete []m_pData;//删除原来的内存
m_pData = temp;
strcpy(m_pData,str.m_pData);//字符串拷贝
return *this;
}
3.考虑异常安全性(2)
创建临时实例,交换临时实例和原来的实例。利用析构函数自动释放已有的内存。
CMyString& CMyString::operator =(const CMyString& str){
if(this != &str){//使用!=条件 使临时实例出作用域后自动析构
CMyString strTmp(str);//复制构造函数
//交换临时实例和当前实例的char*
char* temp = strTmp.m_pData;
strTmp.m_pData = m_pData;
m_pData = temp;
}
//自动释放临时实例
return *this;
}
考点:
运算符函数、常量引用
什么是内存泄漏
异常安全性