赋值运算符重载函数

本文转自:http://zhedahht.blog.163.com/blog/static/25411174200741543224391/


问题:给出如下CMyString的声明,要求为该类型添加赋值运算符函数。

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


当面试官要求应聘者定义一个复制运算符函数时,他会关注如下几点:

·         是否把返回值的类型声明为该类型的引用,并在函数结束前返回实例自身(即*this)的引用?只有返回一个引用,才可以允许连续赋值。否则如果函数的返回值是void,假设有三个CMyString的对象,str1str2str3,在程序中语句str1=str2=str3将不能通过编译。

·         是否把传入的参数的类型声明为常量引用?如果传入的参数不是引用而是实例,那么从形参到实参会调用一次构造拷贝函数。把参数申明为引用可以避免这样的无谓消耗,能提高代码的效率。同时,我们在赋值运算符函数内是不会改变传入的实例的状态的,因此应该为传入的引用参数加上const关键字。

·         是否记得释放实例自身已有的内存?如果忘了在分配新内存之前释放自身已有的空间,将出现内存泄露。

·         是否判断传入的参数是不是和当前的实例(*this)是不是同一个实例?如果是同一个,则不进行赋值操作,直接返回。如果事先不判断,就进行赋值,那么在释放实例自身的内存的时候就会导致严重的问题:当*this和传入的参数是同一个实例时,那么一旦释放了自身的内存,传入的参数的内存也同时被释放了,因此再也找不到需要赋值的内容了。

下面是完整的代码:

/***********
CMyString.h
************/
class CMyString
{
public:
	//默认构造函数
	CMyString();
	//带参数的构造函数
	CMyString(const char *str);
	//拷贝构造函数
	CMyString(const CMyString& str);
	//赋值构造函数
	CMyString& operator= (const CMyString& str);
	~CMyString();
	void Print();
private:
	char *m_pData;
};

/***********
CMyString.cpp
************/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include "CMyString.h"

using namespace std;

//初始给字符串对象分配一个空间,存储'\0'
CMyString::CMyString()
{
	m_pData = new char[1];
	if(NULL == m_pData)
	{
		printf("No more memory\n");
		m_pData = NULL;
	}
	else
		m_pData[0] = '\0';

}

//拷贝形参字符串的内容的内容
CMyString::CMyString(const char *str)
{
	if(NULL == str)
	{
		m_pData = new char[1];
		if(NULL == m_pData)
		{
			printf("No more memory\n");
		}
		else
			m_pData[0] = '\0';
	}
	else
	{
		int len = strlen(str);
		m_pData = new char[len + 1];
		if(NULL == m_pData)
		{
			printf("No more memory\n");
		}
		else
		{
			strcpy(m_pData,str);
			m_pData[len] = '\0';
		}
	}
}

/*复制构造函数,传入的参数是常引用,这样就避免了传参时,从形参到实参会调用一次构造拷贝函数,
因为不改变参数值得内容,所以声明为const引用*/
CMyString::CMyString(const CMyString& str)
{
	if(NULL == str.m_pData)
	{
		m_pData = new char[1];
		if(NULL == m_pData)
		{
			printf("No more memory\n");
		}
		else
			m_pData[0] = '\0';
	}
	else
	{
		int len = strlen(str.m_pData);
		m_pData = new char[len + 1];
		if(NULL == m_pData)
		{
			printf("No more memory\n");
		}
		else
		{
			strcpy(m_pData,str.m_pData);
			m_pData[len] = '\0';
		}
	}
}

//析构函数,释放空间后,置成员指针变量m_pData为空
CMyString::~CMyString()
{
	if(NULL != m_pData)
	{
		delete m_pData;
		m_pData = NULL;
	}
}
/*1、返回值的类型声明为该类型的引用,并在函数结束前返回实例自身(即*this)的引用,这样才允许连续赋值
2、传入的参数的类型声明为常量引用,如果传入的参数不是引用而是实例,那么从形参到实参会调用一次构造拷贝函数,
把参数申明为引用可以避免这样的无谓消耗,能提高代码的效率,
同时,我们在赋值运算符函数内是不会改变传入的实例的状态的,因此应该为传入的引用参数加上const关键字。
3、记得释放实例自身已有的内存,避免出现内存泄露
4、判断传入的参数是不是和当前的实例(*this)是不是同一个实例?如果是同一个,则不进行赋值操作,直接返回。
如果事先不判断,就进行赋值,那么在释放实例自身的内存的时候就会导致严重的问题:当*this和传入的参数是同一个实例时,
那么一旦释放了自身的内存,传入的参数的内存也同时被释放了,因此再也找不到需要赋值的内容了。*/
CMyString& CMyString::operator =(const CMyString &str)
{
	if(this != &str)
	{
		int len = strlen(str.m_pData);
		char *pStr = new char[len+1];
		if(NULL == pStr)
		{
			printf("No more memory\n");
		}
		else
		{
			strcpy(pStr,str.m_pData);
			//记得释放实例自身已有的内存,避免出现内存泄露
			delete m_pData;
			m_pData = pStr;
		}
	}
	return *this;
}

void CMyString::Print()
{
	if(NULL != m_pData)
		printf("%s\n",m_pData);
}

/***********
main.cpp
************/
#include <iostream>
#include <stdio.h>
#include "CMyString.h"

int main()
{
	//char str[] = "Hello World";
	CMyString str1("Hello World5");
	str1 = str1;
	CMyString str2("Good Morning!");
	CMyString str3 = str2 = str1;
	str2.Print();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值