剑指offer学习-赋值运算符重载

首先让我们先看一下浅层复制引起的指针悬挂

#include<iostream>
using namespace std;
class STRING
{
public:
	STRING(char *s)
	{
		ptr=new char[strlen(s)+1];
		strcpy(ptr,s);
	}
	void Show()
	{
		puts(ptr);
	}
	~STRING()
	{
		delete[] ptr;
	}
private:
	char *ptr;
};
int main()
{
	STRING str1("aaaa");
	STRING str2("bbbb");
	str1.Show();
	str2.Show();
	str1=str2;
//	str1.Show();
}
上述程序在运行时会报错,原因就在于str1=str2这句。

程序开始运行时,创建对象str1和str2,分别调用构造函数,通过运算符new分别从内存中动态分配了一块空间,字符指针ptr指向内存空间执行语句str1=str2时,由于用户没有定义赋值运算符函数,所以就调用了默认的赋值运算符函数,使两个对象str1和str2的指针ptr都指向了new开辟的同一空间,这个空间的字符串为“aaaa”。主程序执行结束后,对象逐个撤销,先撤销str2,调用析构函数并用delete释放动态分配的内存空间。然后撤销str1,第二次调用析构函数,尽管这时str1的指针ptr存在,但其所指向的空间却无法访问了,出现了指针悬挂。指针悬挂所引起的问题不止是程序崩溃,还有内存泄露,对象str2中的ptr指针原先所指向的动态空间“bbbb”将一直不会释放,造成内存泄露。


下面是剑指offer中所提出的适于初级程序员的解法

#include<iostream>
using namespace std;
class STRING
{
public:
	STRING(char *s)
	{
		m_pDada=new char[strlen(s)+1];
		strcpy(m_pDada,s);
	}
	~STRING()
	{
		delete[] m_pDada;
	}
	void Show()
	{
		puts(m_pDada);
	}
	STRING &STRING::operator=(const STRING &s);
private:
	char *m_pDada;

};
STRING& STRING::operator=(const STRING &s)
{
	if(this==&s)
	{
		return *this;
	}
	delete[] m_pDada;
	m_pDada=new char[strlen(s.m_pDada)+1];
	strcpy(m_pDada,s.m_pDada);
	return *this;
}
int main()
{
	STRING str1("mybook");
	STRING str2("jeep");
	STRING str3("aaaa");
	str1.Show();
	str2.Show();
	str3.Show();
	str3=str2=str1;
	str3.Show();
	
	return 0;
}

书中提出来初级软件工程师要注意的四个点

1.是否把返回值声明为该类型的引用,并在函数结束前返回实例自身的引用。

2.是否把传入参数的类型声明为常量引用。

3.是否释放实例自身已有的内存。

4.是否判断传入的参数和当前实例是不是同一个实例。


还有一点需要注意的就是赋值运算符只能重载为成员函数,而不能重载为友元函数。当然这个错误也很少有人去犯。

下面是一个考虑程序安全性的解法

STRING& STRING::operator=(const STRING &s)
{
	if(this!=&s)
	{
		STRING strTemp(s);
		char *pTemp=strTemp.m_pDada;
		strTemp.m_pDada=m_pDada;
		m_pDada=pTemp;
	}
	return *this;
}
在前面的函数中,分配内存前线delete释放实例m_Data的内存,如果此时内存不足将导致new char抛出异常,m_Data将是一个空指针。

在下面的函数中,先创建临时变量strTemp,接着把strTemp中的m_Data和实例自身的m_Data交换,由于strTemp是局部变量,当程序运行到if外时,就会自动调用析构函数。

在新的代码中,如果内存不足将导致异常,但是此时我们并没有修改原来实例的状态,这样就保证了安全性。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值