題目:如下為型別CMyString的宣告,請為該型別添加賦值運算子函式,
class CMyString{
public:
CMyString(char* pData = https://www.cnblogs.com/tangliang39/p/nullptr);
CMyString(const CMyString& str);
~CMyString(void);
private:
char* m_pData;
};
注意點:
- 是否把回傳值的型別宣告為該型別的參考,并在函式結束前回傳實體自身的參考(*this),只有回傳一個參考,才可以允許連續賦值,否則,如果函式的回傳值是void,則應用該賦值運算子將不能進行連續賦值,
- 是否把傳入的引數型別宣告為常量參考,如果傳入的引數不是參考而是實體,那么從形參到實參會呼叫一次復制建構式,把引數宣告為參考可以避免這樣的無謂消耗,能提高代碼的效率,同時,我們在復制運算子函式內不會改變傳入的實體狀態,因此應該為傳入的參考引數加上const關鍵字,
- 是否釋放實體自身已有的記憶體,如果我們忘記在分配新記憶體之前釋放自身已有的空間,則程式將出現記憶體泄漏,
- 判斷傳入的引數和當前的實體(this)是不是同一個實體,如果是同一個,則不進行復制操作,直接回傳,如果事先不判斷就進行賦值,那么在釋放實體自身記憶體的時候就會導致嚴重的問題:當this和傳入的引數是同一個實體時,一旦釋放了自身的記憶體,傳入的引數的記憶體也同時被釋放了,因此再也找不到需要賦值的內容了,
經典的解法,適用于初級程式員
//當我們完整的考慮了上述4個方面后,可以寫出如下的代碼:
CMyString& CMyString::operator=(const CMyString& str){
if(this == &str)
return *this;
delete[] m_pData;
m_pData = https://www.cnblogs.com/tangliang39/p/nullptr;
m_pData = new char[strlen(str.m_pData) + 1];
strcpy(m_Data, str.m_pData);
return *this;
}
考慮例外安全性的解法,高級程式員必備
/*在前面的函式中,我們分配記憶體之前先用delete釋放了實體m_pData的記憶體,如果此時記憶體不足導致new char拋出例外,則m_pData將是一個指標,這樣非常容易導致程式崩潰,也就是說,一旦在復制運算子函式內部拋出一個例外,CMyString的實體不在保持有效的狀態,這就違背了例外安全性(Exception Safety)原則,要想在賦值運算子函式中實作例外安全性,我們可以先創建一個臨時實體,再交換臨時實體和原來的實體,下面是這種思路的參考代碼:*/
CMyString& CMyString::operator=(const CMyString& str){
if(this != &str){
CMyString strTemp(str);
char* pTemp = strTemp.m_pData;
strTemp.m_pData = https://www.cnblogs.com/tangliang39/p/m_pData;
m_pData = pTemp;
}
return *this;
}
測驗用例:
- 把一個CMyString的實體賦值給另一個實體,
- 把一個CMyString的實體賦值給它自己,
- 連續賦值,
測驗代碼:
void CMyString::Print(){
printf("%s", m_pData);
}
void Test1(){
printf("Test1 begins:\n");
char* text = "Hello world";
CMyString str1(text);
CMyString str2;
str2 = str1;
printf("The expected result is: %s.\n", text);
printf("The actual result is: ");
str2.Print();
printf(".\n");
}
//賦值給自己
void Test2(){
printf("Test2 begins:\n");
char* text = "Hello world";
CMyString str1(text);
str1 = str1;
printf("The excepted result is: %s.\n", text);
printf("The actual result is: ");
str1.Print();
printf(".\n");
}
//連續賦值
void Test3(){
printf("Test3 begins:\n");
char* text = "Hello world";
CMyString str1(text);
CMyString str2, str3;
str3 = str2 = str1;
printf("The expected result is: %s.\n", text);
printf("The actual result is: ");
str2.Print();
printf(".\n");
printf("The expected result is: %s.\n", text);
printf("The actual result is: ");
str3.Print();
printf(".\n");
}
本題考點:
- 考查應聘者對C++基礎語法的理解,如運算子函式、常量參考等,
- 考查與應聘者對記憶體泄漏的理解,
- 對于高級C++程式員,面試官還將考查應聘者對代碼例外安全性的理解,
實作代碼:
#include <cstring>
#include <cstdio>
class CMyString{
public:
CMyString(char* pData = https://www.cnblogs.com/tangliang39/p/nullptr);
CMyString(const CMyString& str);
~CMyString(void);
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 = https://www.cnblogs.com/tangliang39/p/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){
if(this == &str)
return *this;
delete[] m_pData;
m_pData = nullptr;
m_pData = new char[strlen(str.m_pData) + 1];
strcpy(m_pData, str.m_pData);
return *this;
}
int main(){
Test1();
Test2();
Test3();
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/95040.html
標籤:C++
上一篇:圖資料型別的定義
下一篇:紀念品分組(貪心、排序)
