賦值運算子過載函式 返回引用和返回物件的區別
阿新 • • 發佈:2019-01-03
先上程式碼
#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;
返回物件執行效果如下,請仔細除錯下,為什麼是這樣的結果
返回引用執行效果如下