1. 程式人生 > >賦值運算子過載函式 返回引用和返回物件的區別

賦值運算子過載函式 返回引用和返回物件的區別

先上程式碼

#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;
返回物件執行效果如下,請仔細除錯下,為什麼是這樣的結果
這裡寫圖片描述
返回引用執行效果如下
這裡寫圖片描述