您的位置:首页 > 其它

赋值运算符重载函数 返回引用和返回对象的区别

2016-04-14 10:19 162 查看
先上代码

#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: