劍指offer面試題1——類中的賦值運算符函數

題目:類型CMyString的類聲明中,爲該類型添加賦值運算符函數。

解題思路:
1.賦值運算符函數:是一種重載運算符。本質上也是一種函數。因此,有函數對應的特性:返回值、函數名、形參列表。

class CMyString
{
public:
    CMyString(char* pData=nullptr);
    CMyString(const CMyString& str);
    ~CMyString();

    CMyString& operator=(const CMyString& str);     
    void Print();


private:
    char* m_pData;      //指針指向字符數組的首地址
};
  • ①賦值運算符重載的函數名:operator=
  • ②返回值類型通常使用該類型的引用 CMyString&:目的是爲了能夠連續賦值,如定義3個對象,str3=str2=str1
  • ③形參const CMyString& str 爲常量引用。若不使用引用而是用實例,則從形參到實參會再調用一次拷貝構造函數,是一種無謂的消耗;此外,由於傳入的實例一般不會改變,因此使用常量。
  • ④賦值之前,首先要判斷當前實例和傳入的參數是否爲同一個實例。如果是,則不需要賦值。
  • ⑤賦值的時候,要釋放掉當前實例的內存空間,然後分配新的內存。
  • ⑥在⑤的基礎上,考慮異常安全性問題,旨在避免內存溢出,可以有兩種解決思路: 第一種,先new分配內容,然後再釋放已有的內容;第二種,構建一箇中間變量保存當前實例。

實驗代碼如下:


/************************************************************************/
/*      劍指offer1:賦值運算符函數operator=                          */
/************************************************************************/
#include <string.h>
class CMyString
{
public:
    CMyString(char* pData=nullptr);
    CMyString(const CMyString& str);
    ~CMyString();

    CMyString& operator=(const CMyString& str);     //返回類型用類的引用(目的:多次進行賦值);形參列表用常量引用(引用:避免了從形參到實參還要調用一次拷貝構造函數;常量是因爲傳入示例不會改變
    void Print();


private:
    char* m_pData;      //指針指向字符數組的首地址
};

/************************************************************************/
/*          實現構造函數                                                    */
/************************************************************************/
CMyString::CMyString(char* pData)
{
    if (pData==nullptr)
    {
        m_pData=new char[1];
        m_pData[0]='\0';
    }
    else
    {
        int length = strlen(pData);
        m_pData =new char[length+1];
        strcpy(m_pData,pData);
    }

}

/************************************************************************/
/*          實現拷貝構造函數                                                                     */
/************************************************************************/
CMyString::CMyString(const CMyString& str)
{
    int length=strlen(str.m_pData);
    m_pData=new char[length+1];
    strcpy(m_pData,str.m_pData);
}

/************************************************************************/
/*          析構函數                                                                     */
/************************************************************************/
CMyString::~CMyString()
{
    delete[] m_pData;
}

/************************************************************************/
/*                    類的操作符重載                                                  */
/************************************************************************/
CMyString& CMyString::operator=(const CMyString& str)
{
    //①首先判斷兩個示例是否相等,返回*this(實例自身的引用)
    if (this==&str)
    {
        return *this;
    }

    //②釋放被賦值的實例已有內存,this指針隱含地指向數據delete this->m_pData;
    delete []m_pData;                   //注意:釋放後指針爲空指針
    m_pData=nullptr;

    //③申請新的空間並賦值
    m_pData=new char(sizeof(strlen(str.m_pData)+1));
    strcpy(this->m_pData,str.m_pData);

    return *this;

}

void CMyString::Print()
{
    printf("%s\n",m_pData);

}

void test1()
{
    printf("給另一個量賦值:\n");

    char *text ="hello world";
    CMyString str1(text);
    CMyString str2;
    str2=str1;
    printf("期望的結果爲:%s\n",text);
    printf("實際操作結果爲:");
    str2.Print();
    printf("\n");

}

void test2()
{
    printf("\n\n給自己賦值\n");
    char *text="hello world";
    CMyString str1(text);
    str1=str1;
    printf("期望的結果爲:%s\n",text);
    printf("實際操作結果爲:");
    str1.Print();
    printf("\n");
}


void test3()
{
    printf("\n\n連續賦值:\n");
    char *text="hello world";
    CMyString str1(text);
    CMyString str2,str3;
    str3=str2=str1;

    printf("期望的結果爲:%s\n",text);
    printf("實際操作結果爲:");
    str2.Print();
    printf("\n");
    str3.Print();
    printf("\n");
}

int main()
{
    test1();
    test2();
    test3();

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章