您的位置:首页 > 职场人生

剑指offer面试题1之赋值运算符函数

2016-03-16 12:45 399 查看
//要写一个赋值运算符函数,即重载赋值运算符,有两种形式:类成员函数和友元函数;我们这里用类成员函数的形式
#pragma once

class CMyString
{
public:
//CMyString(void);//这个构造函数和CMyString(char* pdata = NULL)一定程度上重定义了,当定义
//CMyString类型对象时,若都不传参,即用CMyString A;不知道调用哪一个了;
//但CMyString A(NULL)就可以,但还是有警告多次定义构造函数!但当把=NULL去掉就
//不会重定义了,因为去掉后,该构造函数需要传参才会被调用。
~CMyString(void);
//CMyString(char* pdata):m_pdata(pdata){}//这里声明和定义一起了(参数初始化列表)
CMyString(char* pdata = NULL);//这里是默认m_pdata为NULL,即CMyString A;那A.m_pdata = NULL;
CMyString(const CMyString& str);//拷贝构造函数,加const是为了不改变参数的状态
//加&是为了避免调用拷贝构造函数时,由形参到实参调用拷贝构造函数
//从而变成死循环!所以C++标准不允许拷贝构造函数传值参数
CMyString& operator =(const CMyString& str);//重载赋值运算符函数,参数为引用,避免从形参到实参调用
//一次拷贝构造函数,这是无谓消耗,避免
//只有返回一个引用才能连续赋值
public:
char* m_pdata;

};


#include "StdAfx.h"
#include "CMyString.h"

//CMyString::CMyString(void)
//{
//}

CMyString::~CMyString(void)
{
}
CMyString::CMyString(const CMyString& str)
{
this->m_pdata = str.m_pdata;
}
CMyString::CMyString(char* pdata)//这里不能加=NULL,否则会报重定义的错误
{
this->m_pdata = pdata;
}
//CMyString& CMyString::operator =(const CMyString& str)//初级程序员做法,考虑点为:
//{                                              //1,判断传入的实例和当前实例是不是同一个实例,若是,直接返回
//	                                           //2,是否释放实例自身的内存,若忘记,会出现内存泄露
//	                                           //3,传参是否为常量引用,为了高效,避免无谓消耗
//	                                           //4,返回值是否为该类型的引用,为了可以连续赋值
//	if (this == &str)//若不判断,那么在释放内存后,传入参数也被释放了,再也找不到赋值内容了。
//	{
//		return *this;
//	}
//	else
//    {
//		delete[] m_pdata;//释放该实例的空间
//		m_pdata = NULL;//避免野指针
//		m_pdata = new char[strlen(str.m_pdata) + 1];
//		strcpy(m_pdata, str.m_pdata);
//		return *this;
//    }
//
//}
//为什么说是初级程序员呢?
//因为没有考虑异常安全性原则,我们在分配内存之前就释放了实例的内存,那么若new char不成功,抛出异常
//那么m_pdata将是一个空指针,赋值没成功不止,还把原来的自己丢了。
//该进!!!!!
//第一种是:让一个局部指针指向m_pdata,再new一个空间,若成再释放这个局部变量指向的空间
//主要看第二种:
CMyString& CMyString::operator =(const CMyString& str)
{
if (this != &str)
{
CMyString str_temp(str);
char* ptemp = str_temp.m_pdata;
str_temp.m_pdata = m_pdata;
m_pdata = ptemp;//就是把局部变量m_pdata指向位置和该实例m_pdata指向位置互换
}
return *this;
}
//这好在哪呢?
//1,先创建一个临时实例,若不成功,抛出异常,不影响原来的自己,保证了异常安全性。
//2,若创建成功,str_temp是局部变量,作用域在if中,出了if就自动调用析构函数,而我们
//把str_temp.m_pdata和原来自己的m_pdata互换了,这时候析构的就是原来自己的空间了。


#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
#include "CMyString.h"
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
//CMyString A(NULL);
char *a = new char[10];
string temp = "hello!!";
stringstream ss;
ss << temp;
ss >> a;
CMyString A(a);
//测试用例1
CMyString B = A;
printf("%s\n", B);
//测试用例2
CMyString C;
C = B = A;
//cout << C.m_pdata;//m_pdata改成public可以
printf("%s\n", C);
//测试用例3
B = B;
printf("%s", B);
system("pause");
return 0;
}
//输出结果为:hello!!
//            hello!!
//            hello!!请按任意键继续...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: