
1 #include <cstring> 2 #include <cstdio> 3 using namespace std; 4 5 class CMyString 6 { 7 public: 8 CMyString(char* pData=nullptr); 9 CMyString(const CMyString& str); 10 CMyString& operator=(const CMyString& str); 11 ~CMyString(); 12 13 void Print(); 14 private: 15 char* m_pData; 16 }; 17 18 CMyString::CMyString(char *pData) 19 { 20 if (pData == nullptr) 21 { 22 m_pData = new char[1]; 23 m_pData[0] = '\0'; 24 } 25 else 26 { 27 int length = strlen(pData); 28 m_pData = new char[length + 1]; 29 strcpy_s(m_pData, length + 1, pData); 30 } 31 } 32 CMyString::CMyString(const CMyString& str) 33 { 34 int length = strlen(str.m_pData); 35 m_pData = new char[length+1]; 36 strcpy_s(m_pData, length + 1, str.m_pData); 37 } 38 CMyString::~CMyString() 39 { 40 delete[] m_pData; 41 } 42 CMyString& CMyString::operator=(const CMyString& str) 43 { 44 if (this == &str) return *this; 45 CMyString strTemp(str); 46 char* pTemp = strTemp.m_pData; 47 strTemp.m_pData = m_pData; 48 m_pData = pTemp; 49 return *this; 50 } 51 void CMyString::Print() 52 { 53 printf("%s", m_pData); 54 }
定義一個賦值運算符時需要考慮的要點:
- 把返回值聲明為該類型的引用,並在函數結束時前返回實例自身的引用。這樣才可以允許連續賦值。
- 傳入的參數需要聲明為常量引用,如果傳入的參數不是引用而是實例,則從形參到實參會調用一次復制構造函數。
- 釋放實例自身已有的內存,如果在分配新內存前忘記釋放自己已有的內存,則會出現內存泄漏。
- 判斷傳入參數與當前實例是不是同一個實例,如果是同一個,則立即返回。如果事先不判斷會導致嚴重的問題,一旦釋放了自身的內存,傳入的參數的內存也同時被釋放了,因此再也找不到需要賦值的內容了。
- 考慮異常情況,如果使用new時拋出異常,則m_pData指向的內存已被釋放,則m_pData將是一個空指針,很容易導致程序崩潰。