題目:類型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();
}