標籤:ext cte 運算 text 事先 == new 應聘 c++
一.題目
如下為類型CMyString的聲明,請為該類型添加賦值運算子函數。
class CMyString{public: CMyString(char* pData = nullptr); CMyString(const CMyString& str); ~CMyString(void); CMyString& operator = (const CMyString& str); void Print();private: char* m_pData;};二.注意點
- 是否把傳回值的型別宣告為該類型的引用,並在函數結束前返回執行個體自身的引用(*this)。只有返回一個引用,才可以允許連續賦值。否則,如果函數的傳回值是void,則應用該賦值運算子將不能進行連續賦值。
- 是否把傳入的參數的型別宣告為常量引用。如果傳入的參數不是引用而是執行個體,那麼從形參到實參會調用一次複製建構函式。把參數聲明為引用可以避免這樣的無謂消耗,能提高代碼的效率。同時,我們在賦值運算子函數內不會改變傳入的執行個體的狀態,因此應該為傳入的引用參數加上const關鍵字。
- 能否釋放執行個體自身已有的記憶體。如果我們忘記在分配新記憶體之前釋放自身已有的空間,則程式將會出現記憶體泄露。
- 判斷傳入的參數當前的執行個體(*this)是不是同一個執行個體。如果是同一個,則不進行賦值操作,直接返回。如果事先不判斷就進行賦值,那麼在釋放執行個體自身記憶體的同時就會導致嚴重的問題:當*this 和傳入的參數是同一個執行個體時,一旦釋放了自身記憶體,傳入的參數的記憶體也同時釋放了,因此再也找不到需要賦值的內容了
考慮到上述問題,就能較好的解決問題;但是,如果使程式更加魯棒,我們應該考慮異常安全性。有兩種方法:
- 先用new分配新內容,再用delete釋放已有的內容
- 先建立一個臨時執行個體,再交換臨時執行個體和原來的執行個體
三.代碼
#include <cstdio>#include <cstring>class CMyString {public: CMyString(char* pData = nullptr); CMyString(const CMyString& str); CMyString& operator = (const CMyString& str); void Print(); ~CMyString(void);private: char* m_pData;};CMyString::CMyString(char* pData) { if(pData == nullptr) { m_pData = new char[1]; m_pData[0] = ‘\0‘; } else { int len = strlen(pData); m_pData = new char[len + 1]; strcpy(m_pData,pData); }}CMyString::CMyString(const CMyString& str) { int len = strlen(str.m_pData); m_pData = new char[len + 1]; strcpy(m_pData,str.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;////}CMyString& CMyString::operator = (const CMyString& str) { if(this != &str) { CMyString strTmp(str); char* pTmp = strTmp.m_pData; strTmp.m_pData = m_pData; m_pData = pTmp; } return *this;}void CMyString::Print() { printf("%s", m_pData);}CMyString ::~CMyString() { delete[] m_pData;}//=================TEST==================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 expected 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 actual result is "); str3.Print(); printf(".\n");}int main() { Test1(); Test2(); Test3(); return 0;}四.本題考點
- 本體考查應聘者對C++基礎文法的理解,如運算子函數、常量引用等
- 考察應聘者對記憶體泄露的理解
- 對於進階C++程式員,面試官還將考查應聘者對代碼異常安全性的理解
面試題1:賦值運算子函數