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

Posted Wecccccccc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[剑指offer]面试题1:赋值运算符函数相关的知识,希望对你有一定的参考价值。

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

class CMyString
{
public:
	CMyString(char *pData = nullptr);

	CMyString(const CMyString &str);
	~CMyString(void);
private:
	char *m_pDate;
};

经典解法,适用初级程序员:

CMyString & CMyString::operator=(const CMyString &str)
{
	if (this == &str) return *this;
	delete[] m_pDate;
	m_pDate = nullptr;
	m_pDate = new char[strlen(str.m_pDate) + 1];
	strcpy(m_pDate, str.m_pDate);

	return *this;
}

在前面的函数中,我们在分配内存之前先用delete释放了实例m_pData的内存。如果此时内存不足导致new char抛出异常,m_pData将是一个空指针,这样非常容易导致程序崩溃。也就是说一旦在赋值运算符函数内部抛出一个异常,CMyString的实例不再保持有效的状态,这就违背了异常安全性(Exception Safety)原则。
(通俗来说,就是我们new空间的时候,如果此时内存不足,就new不出来,编译器就会报错,可这个时候我们原来的CMyString的m_pDate被我们释放了)

解决方法一:
我们先用new分配新内容再用delete释放已有的内容。这样只在分配内容成功之后再释放原来的内容,也就是当分配内存失败时我们能确保 CMyString 的实例不会被修改。

解决方法二(更好):
先创建一个临时实例,再交换临时实例和原来的实例。

解法二代码如下:

CMyString & CMyString::operator=(const CMyString &str)
{
	if (this != &str)
	{
		CMyString strTemp(str);
		char *pTemp = strTemp.m_pDate;
		strTemp.m_pDate = m_pDate;
		m_pDate = pTemp;
	}

	return *this;
}

在这个函数中,我们先创建一个临时实例 strTemp,接着把strTemp.m_pData和实例自身的m_pData做交换。
由于strTemp是一个局部变量,但程序运行到 if 的外面时也就出了该变量的作用域,就会自动调用strTemp 的析构函数,把 strTemp.m_pData 所指向的内存释放掉。
由于strTemp.m_pData指向的内存就是实例之前m_pData的内存,这就相当于自动调用析构函数释放实例的内存。
在新的代码中,我们在CMyString的构造函数里用new分配内存。
如果由于内存不足抛出诸如bad_alloc等异常,我们还没有修改原来实例的状态,因此实例的状态还是有效的,这也就保证了异常安全性。

测试用例:
● 把一个CMyString的实例赋值给另外一个实例。
● 把一个CMyString的实例赋值给它自己。
● 连续赋值。
本题考点:
● 考查对C++的基础语法的理解,如运算符函数、常量引用等。
● 考查对内存泄露的理解。
● 对高级C++程序员,面试官还将考查应聘者对代码异常安全性的理解。

以上是关于[剑指offer]面试题1:赋值运算符函数的主要内容,如果未能解决你的问题,请参考以下文章

剑指Offer之赋值运算符重载(题1)

剑指offer编程题Java实现——面试题10二进制中1的个数

剑指offer:赋值运算符函数

[剑指offer]面试题47:不用加减乘除做加法

《剑指Offer——面试题30. 包含min函数的栈》代码

赋值运算符函数 剑指offer