赋值运算符重载函数 返回引用和返回对象的区别
2016-04-14 10:19
162 查看
先上代码
一、如果赋值运算符返回的是返回对象本身
执行结果如下图所示
1 释放对象原来的堆资源
2 重新申请堆空间
3 拷贝源的值到对象的堆空间的值
4 创建临时对象(调用临时对象拷贝构造函数),将临时对象返回
5. 临时对象结束,调用临时对象析构函数,释放临时对象堆内存
注意:如果第4步,我们没有定义拷贝构造函数,也就是没有进行深拷贝。那么在进行第5步释放临时对象的heap 空间时,将释放掉的是和目标对象同一块的heap空间。这样当目标对象B作用域结束调用析构函数时,就会产生错误!!
因此,如果赋值运算符返回的是类对象本身,那么一定要重载类的拷贝构造函数(进行深拷贝)!
二:如果赋值运算符返回的是对象的引用
执行结果如下图所示
1 释放对象原来的堆资源
2 重新申请堆空间
3 拷贝源的值到对象的堆空间的值
4 返回源对象的引用
5 结束。
因此,如果赋值运算符返回的是对象引用,那么其不会调用类的拷贝构造函数,这是返回对象和返回引用的主要区别,返回引用的效率明显较高,
如果你把代码换成
(liubei = guanyu) = zhangfei;
返回对象执行效果如下,请仔细调试下,为什么是这样的结果
返回引用执行效果如下
参考文献:
http://blog.chinaunix.net/uid-24876683-id-206802.html
#include "stdafx.h" #include <string> using namespace std; class CStudent { public: CStudent(char *pName) :m_pName(NULL) { if (NULL == pName) { return; } m_pName = new char[strlen(pName) + 1]; strcpy(m_pName, pName); printf("CStudent: address:0x%08x name:%s\n", this, m_pName); } ~CStudent() { printf("~CStudent: address:0x%08x name:%s\n", this, m_pName); delete m_pName; } //拷贝构造函数 CStudent(const CStudent &a) :m_pName(NULL) { if (NULL == a.m_pName) { return; } int len = strlen(a.m_pName); this->m_pName = new char[len + 20]; memset(m_pName, 0, len + 20); strcpy(m_pName, a.m_pName); strcat(m_pName, "_copy_construct"); // 为了测试 printf("copy construct: address:0x%08x name:%s\n", this, this->m_pName); } public: #if 01 //重载赋值函数 返回对象 CStudent operator=(const CStudent &b) { if (&b == this) { return *this; } if (NULL == b.m_pName) { delete m_pName; m_pName = NULL; return *this; } delete m_pName; int len=strlen(b.m_pName); m_pName=new char[len+1]; memset(m_pName, 0, len+1); strcpy(m_pName,b.m_pName); return *this; } #else //重载赋值函数 返回引用 CStudent& operator=(const CStudent &b) { if (&b == this) { return *this; } if (NULL == b.m_pName) { delete m_pName; m_pName = NULL; return *this; } delete m_pName; int len = strlen(b.m_pName); m_pName = new char[len + 1]; memset(m_pName, 0, len+1); strcpy(m_pName, b.m_pName); return *this; } #endif //或者 我们也可以这样重载赋值运算符 即不返回任何值。如果这样的话,他将不支持客户代买中的链式赋值 //例如a=b=c will be prohibited! //void operator=(const CStudent &a); private: char *m_pName; }; int main() { { CStudent liubei("liubei"); CStudent guanyu("guanyu"); CStudent zhangfei("zhangfei"); //CStudent dd(NULL); //CStudent ff(dd); liubei = guanyu = zhangfei; } system("pause"); return 0; }
一、如果赋值运算符返回的是返回对象本身
执行结果如下图所示
1 释放对象原来的堆资源
2 重新申请堆空间
3 拷贝源的值到对象的堆空间的值
4 创建临时对象(调用临时对象拷贝构造函数),将临时对象返回
5. 临时对象结束,调用临时对象析构函数,释放临时对象堆内存
注意:如果第4步,我们没有定义拷贝构造函数,也就是没有进行深拷贝。那么在进行第5步释放临时对象的heap 空间时,将释放掉的是和目标对象同一块的heap空间。这样当目标对象B作用域结束调用析构函数时,就会产生错误!!
因此,如果赋值运算符返回的是类对象本身,那么一定要重载类的拷贝构造函数(进行深拷贝)!
二:如果赋值运算符返回的是对象的引用
执行结果如下图所示
1 释放对象原来的堆资源
2 重新申请堆空间
3 拷贝源的值到对象的堆空间的值
4 返回源对象的引用
5 结束。
因此,如果赋值运算符返回的是对象引用,那么其不会调用类的拷贝构造函数,这是返回对象和返回引用的主要区别,返回引用的效率明显较高,
如果你把代码换成
(liubei = guanyu) = zhangfei;
返回对象执行效果如下,请仔细调试下,为什么是这样的结果
返回引用执行效果如下
参考文献:
http://blog.chinaunix.net/uid-24876683-id-206802.html
相关文章推荐
- 设计模式之命令模式(Command)
- 2.2 Android进程间通信(IPC)----Service Manager
- NavigationBar 下面的横线是怎么来的? 如何去除?
- 实现HorizontalScrollView随ViewPager滚动的简易方法
- Android开发之Fragment与Activity的数据交互通过回调机制实现
- Android动画
- Android屏幕适配全攻略(最权威的官方适配指导)
- iOS开发 GET、POST请求方法(NSURLConnection篇)
- Python中*args 和**kwargs的用法
- 2. Add Two Numbers(Java)
- 混合编程的实践与思考
- 欢迎使用CSDN-markdown编辑器
- VS2008的程序,运行时遇到R6034错误:
- Java基础学习(一)—方法
- java 深入浅出工厂模式
- Web前端开发笔试&面试_02(others)
- ORA-22835 缓冲区对于 CLOB 到 CHAR 转换或 BLOB 到 RAW 转换而言太小
- IOS Application详解
- the number of position
- 不花软妹币就可以出国了!