赋值运算符函数

/***************************************************************
题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数。
class CMyString
{
public:
	CMyString(char* pData = NULL);
	CMyString(const CMyString& str);
	~CMyString(void);
private:
	char* m_pData;
};
***************************************************************/
#include<stdio.h>
#include<string.h>	//当使用strcpy、strlen、strcat函数时,需要加头文件<string.h>

class CMyString
{
public:
	CMyString(char* pData = NULL);
	CMyString(const CMyString& str);
	~CMyString(void);
	CMyString& operator=(const CMyString& str);//赋值操作符返回类型应为该类型的引用,参数应为常量引用
	friend void  myStrPrint(const CMyString& str);
private:
	char* m_pData;
};

CMyString::CMyString(char* pData)
{
	if(NULL == pData)			//注意参数为指针时,看有没有必要判断是否为NULL
	{
		m_pData = new char[1];	//注意new的用法,p_var = new type [size];
		m_pData[0] = '\0';		//注意字符串结束符号为'\0',而不是'/0'
	}
	else{
		m_pData = new char [strlen(pData) + 1];//注意字符串内存度需要包括字符串结束符
		strcpy(m_pData, pData);//注意strcpy的用法
	}
}
CMyString::CMyString(const CMyString &str)
{
	m_pData = new char [strlen(str.m_pData) + 1];//注意字符串内存大小需要包括字符串结束符
	strcpy(m_pData, str.m_pData);//char *strcpy( char *strDestination, const char *strSource );
}
CMyString::~CMyString()
{
	delete[] m_pData;
}
//一般赋值操作符实现
/*
CMyString& CMyString::operator =(const CMyString &str)
{
	if(this == &str)		//如果是自身赋值,返回自身
		return *this;
	delete[] m_pData;	//否则应该先释放内存,再赋值
	m_pData = NULL;

	m_pData = new char[strlen(str.m_pData)+1];
	strcpy(m_pData,str.m_pData);//赋值

	return *this;
}
*/
//考虑异常安全赋值操作符实现
CMyString& CMyString::operator =(const CMyString &str)
{
	if(this != &str)	//考虑自身赋值
	{
		CMyString strTemp(str);	//创建临时对象,在赋值操作符调用完后会自动释放内存
		char* pTemp = strTemp.m_pData;
		strTemp.m_pData = m_pData;	//依靠临时对象,自动调用析构函数释放实例的内存
		m_pData = pTemp;	//实现赋值
	}
	return *this;
}
//用来测试时输出字符串
void myStrPrint(const CMyString& str){
	printf("%s",str.m_pData);
}
//单元测试测试函数
//普通赋值
void test1()
{
	printf("test1: \n");
	printf("The expected result is:\n");
	CMyString str1("Hello World!");
	myStrPrint(str1);
	printf("\n");
	CMyString str2;
	str2 = str1;
	printf("The actuall result is:\n");
	myStrPrint(str2);
	printf("\n");
}
//自身赋值
void test2()
{
	printf("test2: \n");
	CMyString str1("Hello World!");
	printf("The expected result is:\n");
	myStrPrint(str1);
	printf("\n");
	str1 = str1;
	printf("The actuall result is:\n");
	myStrPrint(str1);
	printf("\n");
}
//连续赋值
void test3()
{
	printf("test2: \n");
	CMyString str1("Hello World!");
	printf("The expected result is:\n");
	myStrPrint(str1);
	printf("\n");
	CMyString str2,str3;
	str3 = str2 = str1;
	printf("The expected result is:\n");
	myStrPrint(str2);
	printf("\n");
	printf("The expected result is:\n");
	myStrPrint(str3);
	printf("\n");
}
//测试
int main()
{
	test1();
	test2();
	test3();
	return 0;
}
/*
当定义赋值运算符函数时,需要关注一下几点:
1.是否把返回值声明为该类型的引用,并在函数结束前返回实例自身的引用(即*this)。
  只有返回一个引用,才可以实现连续赋值
2.是否把传入的参数类型声明为常量引用。可避免调用复制构造函数带来的损耗,提高效率。
3.是否释放自身已有的内存。如果忘记在分配新内存之前释放自身已用的内存,会内存泄露。
4.是否判断传入的参数和当前的实例(*this)是不是同一个实例。如果是同一个,直接返回。

考虑异常安全:
不考虑异常安全的赋值符函数,如果在分配内存时,内存不够,p_Data将是一个空指针,不再
保持有效的状态,容易导致程序崩溃,这不符合异常安全原则。解决办法是在分配内容成功后,
在释放原有内存。还有一个办法是先创建一个临时实例,再交换临时实例和原来的实例,临时
实例内分配失败,原来实例保持不变,仍然是有效状态;若成功,原来实例的原有内存会依靠
临时实例作用结束时自动调用析构函数而释放内存。
*/

==参考剑指offer面试题1

==转载请注明出处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值