剑指offer面试题1:赋值运算符函数

赋值运算符函数

题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数

class CMyString 
{
public:
	CMyString(char * pData=nullptr);
	CMyString(const CMyString &str);
private:
	char * m_pData;
}

要点:

定义赋值构造函数的要点:

  1. 要将函数返回值类型声明为该类型的引用,并在函数结束前返回实例自身的引用(*this),只有返回一个引用,才可以是赋值运算符有连续赋值的功能。

  2. 要将函数传入值的类型声明为常量引用,为了避免引用对象不被修改,且避免调用复制构造函数造成无畏的消耗

    注:调用复制构造函数的时机:

    • 用已有对象初始化创建新对象
    • 类类型传值参数,调用复制构造函数将实参对象初始化形参对象
    • 返回类类型的函数,调用复制构造函数创建临时对象
  3. 要在分配新内存之前释放自身已有空间,否则会出现内存泄漏

  4. 要判断传入参数和当前实例是否是同一个实例,若是则不进行赋值操作。

初级程序员解法:

CMyString &CMyString::operater=(const CMyString &str)
{
	if(*this==&str)//判断传入参数和当前实例是否相同
		return *this;
	delete []m_pData;//分配新内存前释放自身已有空间
	m_pData=nullptr;
	m_pData=new char[strlen(str.m_pData)+1];//分配内存大小
	strcpy(m_pData,str.m_pData);//复制内容
	
	return *this;
}

高级程序员解法:

在上述基础上考虑异常安全性。
满足异常安全性的两个要点:

  1. 不泄露任何资源
  2. 不破坏任何数据

在前面的解法中,我们是先释放内存在分配新空间,一旦释放内存后,分配新空间时发生内存不足,抛出异常,此时就会不满足异常安全性,因为此时数据被破坏,CMyString的实例不在保持有效的状态。

主要思想:创建一个临时实例,再交换临时实例和原来的实例。

CMyString &CMyString::operator(const CMyString &str)
{
	if(*this!=&str)
	{	
		CMyString strTemp(str);//创建临时实例strTemp
		char *pTemp=strTemp.pData;
		strTemp.pData=m_pData;
		m_pData=pTemp;
	}
	return *this;
}

觉得本文对你有帮助,点个赞噢谢谢

你可能感兴趣的:(剑指offer)