博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
赋值运算符重载函数
阅读量:4677 次
发布时间:2019-06-09

本文共 1997 字,大约阅读时间需要 6 分钟。

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

1 class CMyString 2 { 3 public: 4     CMyString(char* pData = NULL); 5     CMyString(const CMyString& str); 6     ~CMyString(void); 7        8 private: 9     char* m_pData;10 };

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

  • 是否把返回值的类型声明为该类型的引用,并在函数结束前返回实例自身(即*this)的引用?只有返回一个引用,才可以允许连续赋值。否则如果函数的返回值是void,假设有三个CMyString的对象,str1str2str3,在程序中语句str1=str2=str3将不能通过编译。
  • 是否把传入的参数的类型声明为常量引用?如果传入的参数不是引用而是实例,那么从形参到实参会调用一次构造拷贝函数。把参数申明为引用可以避免这样的无谓消耗,能提高代码的效率。同时,我们在赋值运算符函数内是不会改变传入的实例的状态的,因此应该为传入的引用参数加上const关键字。
  • 是否记得释放实例自身已有的内存?如果忘了在分配新内存之前释放自身已有的空间,将出现内存泄露。
  • 是否判断传入的参数是不是和当前的实例(*this)是不是同一个实例?如果是同一个,则不进行赋值操作,直接返回。如果事先不判断,就进行赋值,那么在释放实例自身的内存的时候就会导致严重的问题:当*this和传入的参数是同一个实例时,那么一旦释放了自身的内存,传入的参数的内存也同时被释放了,因此再也找不到需要赋值的内容了。

代码如下:

1 CMyString & CMyString::operator=(const CMyString &str) 2 { 3     if(this == &str) 4         return *this; 5  6     delete []m_pData; 7     m_pData = NULL; 8  9     m_pData = new char[strlen(str.m_pData) + 1];10     strcpy(m_pData, str.m_pData);11 12     return *this13 }

     这是一般C++教材上提供的参考代码。如果是面试的是应届毕业生或者C++初级程序员,如果能全面地考虑到前面四点并完整地写出代码,面试官可能会让他通过这轮面试。但如果面试的是C++的高级程序员,面试官可能会提出更高的要求。

     面试官会提醒我们在前面的函数中,显示地用delete释放自身m_pData的内存。同时我们也会在析构函数中用delete释放自身m_pData的内存。如果这个类型中添加新的指针成员变量,那么我们至少需要做两处修改,即同时在析构函数和这个赋值运算符函数里添加一条delete语句来释放新指针所指向的内存。一个改动需要在代码中多个地方修改代码,通常是有安全隐患的。通常我们会记得在析构函数里用delete释放指针成员变量,但未必每次都记得到赋值运算符函数来添加代码释放内存。

     更好的办法在复制运算符函数中利用析构函数自动释放实例已有的内存。

代码如下:

1 CMyString & CMyString::operator=(const CMyString &str) 2 { 3     if(this != &str) 4     { 5         CMyString StringTmp(str); 6         char *cTmp = StringTmp.m_pData; 7         StringTmp.m_pData = m_pData; 8         m_pData = cTmp; 9     }10     return *this;11 }

    这个函数中,我们定义一个临时实例strTemp,并把strTemp的m_pData指向当前实例(*this)的m_pData。由于strTemp是个局部变量,但程序员运行到if的外面是也就出了的该变量的域,就会自动调用strTemp的析构函数,就会把strTemp.m_pData所指向的内存释放掉。由于strTemp.m_pData指向的内存就是当前实例之前m_pData的内存。这就相当于自动调用析构函数释放当前实例的内存。如果新增加指针成员变量,我们只需要在析构函数里正确地释放,而不需要对赋值运算符函数做任何修改。

代码来源:

转载于:https://www.cnblogs.com/phquan/archive/2012/12/05/2803871.html

你可能感兴趣的文章
Centos 配置eth0 提示Device does not seem to be present
查看>>
OS开发入门教程(1)
查看>>
arduino 驱动电调
查看>>
一个游标的性能问题
查看>>
JMeter学习-2 JMeter环境搭建
查看>>
SQL SERVER 2012疑难问题解决方法
查看>>
关于Android RenderScript 的详细说明和一些实用文档
查看>>
POJ1051 P,MTHBGWB
查看>>
士兵队列训练问题
查看>>
播放器
查看>>
linq to entity GroupBy多个字段
查看>>
二叉树遍历 空间复杂度为O(1)
查看>>
关于排序
查看>>
bzoj 3874: [Ahoi2014&Jsoi2014]宅男计划
查看>>
记录-Hibernate+servlet实现简单的增、删、查、改
查看>>
用位运算生成下一个含有k个1的二进制数
查看>>
setContentView()与LayoutInflater.inflate()作用
查看>>
Java魔法堂:注解用法详解——@SuppressWarnings
查看>>
安居客scrapy房产信息爬取到数据可视化(下)-可视化代码
查看>>
HDU1791三点确定一个圆
查看>>