面试题 1:赋值运算符函数
题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数
class CMyString { public: CMyString(char* pData = nullptr); CMyString(const CMyString& str); ~CMyString(void); private: char* m_pData; };
解法一:普通解法
需要考虑以下几点:
- 返回值为该类引用:目的是可进行连续赋值
- 参数为const类型:目的是形参在函数内不可修改
- 参数为引用类型:目的是不调用拷贝构造函数减少消耗
- 赋值前释放原有空间:目的是防止出现内存泄漏
- 最开始要判断自己给自己赋值的情况:如果不进行判断,会导致释放了自身内存后,形参的内存也被释放掉,再也找不到需要赋值的内容了
参考代码
CMyString& operator=(const CMyString& str)
{
// 自己给自己赋值的情况
if(this == &str)
return *this;
// 清空原有数据
if(this->m_pData != nullptr)
{
delete[] this->m_pData;
this->m_pData = nullptr;
}
// 赋值
this->m_pData = new char[strlen(str.m_pData) + 1];
strcpy(m_pData, str.m_pData);
return *this;
}
解法二:考虑异常安全性
需要考虑以下几点:
- 使用new时发生了内存不足的情况,就会抛出异常,此时m_pData将会变成空指针,丢失原有的内容
- 赋值失败时,保证原有内容还存在
解题思路:
- 创建一个和str一模一样的CMyString类型临时变量,交换m_pData指向的内容
参考代码
CMyString& operator=(const CMyString& str)
{
if(this != &str)
{
CMyString tempStr(str); // 如果内存不够,后面的语句将不会被执行,原有内容被保留了下来
char* tempS = tempStr.m_pData;
tempStr.m_pData = this->m_pData;
this->m_pData = tempS;
}
return *this;
}