面试题1

面试题1:赋值运算符


题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数。
class CMyString
{
public:
CMyString(char *pData=NULL);//构造函数
CMyString(const CMyString& str);//拷贝构造函数
~CMyString();//析构函数
private:
char* m_pData;//数据域,字符指针
};


介绍重载赋值

  重载操作符是一些函数,其名字为关键字operator后紧跟需要重载的运算符,比如"operator="表示需要重载"="。像任何其他函数一样,操作符函数有一个返回值和一个形参表。形参表必须具有与该操作符操作数数目相同的形参,但是如果操作符是一个成员函数,它的第一个操作数隐式绑定到this指针,因此形参表中的参数会减少一个。因为赋值运算符必须是类的成员函数,所以this绑定到左操作数的指针。因此,赋值操作符只接受一个形参,且该形参是同一类型的对象,右操作数一般作为const引用传递,跟拷贝构造函数相同。

  赋值操作符的返回类型应该与内置类型赋值运算的返回类型相同,内置类型的赋值运算返回对左操作数的引用,因此赋值操作符也返回对同一类类型的引用。赋值必须返回对*this的引用,也就是左操作数的引用。一般而言,赋值操作符与复合赋值操作符应返回左操作数的引用。

  从上述基础知识我们知道了重载赋值操作符是一个类的成员函数,这个函数的返回类型是左操作数的引用,也就是*this,并且这个函数的参数是一个同类型的常引用变量。通过上述知识我们可以确定重载操作符函数为


写代码是应该注意

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

2.是否把传入的参数类型声明为常量引用。如果传入的参数不是引用而是实例,那么从形参到实参会调用一次复制构造函数。

3.是否释放实力自身的内存。

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

完整代码:

#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;

class Mystring
{
public:
	Mystring(char *data=NULL);
	Mystring(const Mystring& str);
	~Mystring();
	Mystring& operator=(const Mystring& str);
	void Print();
private:
	char* _data;
};
Mystring::Mystring(char *data)
{
   if(data==NULL)
   {
	   _data=new char[1];
	   _data[0]='\0';
   }
   else
   {
	   int len=strlen(data);
	   _data=new char[len+1];
	   strcpy(_data,data);
   }
}

Mystring::~Mystring()
{
	delete[] _data;
}
Mystring::Mystring(const Mystring& str)
{
	int len=strlen(str._data);
	_data=new char[len+1];
	strcpy(_data,str._data);
}
Mystring& Mystring::operator=(const Mystring &str)
{
	if(this==&str)
		return *this;
	
	delete[] _data;
	_data=NULL;
	
	int len=strlen(str._data);
	_data=new char[len+1];
	strcpy(_data,str._data);
}

void Mystring:: Print()
{ 
	cout<<_data<<endl;
}
int main()
{
	char* s="hello world!";
	Mystring str1(s);
	Mystring str2;
	str2=str1;
	str1=str1;

	str1.Print();
	str2.Print();
	system("pause");
	return 0;
}
存在的问题

在上述代码中,我满首先释放自己的内存,然后去开辟一块内存空间让_data指向这块空间,最后进行拷贝,

如果因为内存不足,在new char[len+1]阶段抛出异常,那么这时候因为已经释放了_data,导致_data指向一个空指针,这样可能会导致程序崩溃。有两种方案解决上述问题:

  • 先用new分配新内容,然后删除自己已有内容,最后进行赋值。
  • 创建一个临时实例,交换临时实例与当前实例的_data。代码如下:
    Mystring& Mystring::operator=(const Mystring &str)
    {
    	if(this!=&str)
    	{
    		Mystring strTemp(str);//创建临时实例
    		//交换
    		char* pTemp=strTemp._data;
    		strTemp._data=_data;
    		_data=pTemp;
    	}
    	return *this;
    }

这样的一个好处是在运行完if语句以后,因为除了strTemp的作用于该实例会自动调用析构函数,把strTemp._data所指向的内存释放掉,而此时strTemp._data指向的是实例原先_data指向的内存,并没有释放当前指向的pTemp这一块内存。还有一点是通过构造函数为临时实例分配内存,如果在new char过程中抛出异常,并没有改变该实例_data所指向的内容,也没有释放内存,所以是 异常安全性 的。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值