剑指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!!请按任意键继续...
相关文章推荐
- 菜鸟面试2
- 面试准备之JVM的组成、垃圾回收机制
- 3.14第3次作业,软考高项,第4章与第5章
- java基础面试题
- 十道海量数据处理面试题与十个方法大总结
- 测试开发工程师面试题目
- 剑指offer代码解析——面试题25二叉树中和为某一值的路径
- 剑指offer代码解析——面试题25二叉树中和为某一值的路径
- Java 面试
- 剑指offer代码解析——面试题31连续子数组的最大和
- 剑指offer代码解析——面试题31连续子数组的最大和
- 工作中最让程序员疯狂的5件事
- Java面试宝典2015版(绝对值得收藏超长版)(四)
- 工作中最让程序员疯狂的5件事
- 程序员常用工具
- 分享8年开发经验,浅谈程序员职业规划
- 程序员技术练级攻略
- 常见Android面试题及答案(详细整理)
- Java面试基础
- iOS面试题十