您好,登錄后才能下訂單哦!
string函數的簡單實現如下
class CMyString { public: CMyString(const char*str)//構造函數 { if (str == NULL)//若傳入一個空字符串則直接開辟一個‘\0’的空間 { m_pData = new char[1]; m_pData = '\0'; } else { int length = strlen(str); m_pData = new char[length + 1];//開辟空間 strcpy(m_pData,str);//字符串拷貝 } } CMyString(const CMyString&c) { int length = strlen(c.m_pData); m_pData = new char[length + 1]; strcpy(m_pData, c.m_pData); } ~CMyString(void) { delete[] m_pData; } private: char*m_pData; };
對于賦值運算符函數,重點在于
◆1.函數返回值:函數返回值應該是該類型的引用,只有返回引用才可以實現連續賦值(str1=str2=str3)。同時,在函數結束時返回實例自身的引用,即*this
◆2.函數參數:函數參數因設置為常量引用,若傳入參數為實例而不是引用會再調用一次拷貝構造函數構造一個無名參數,耗時費空間。const使傳入的參數不會被改變
◆3.是否釋放自身已有內存:若不在分配新的空間之前釋放空間,會導致內存泄漏
◆4.自賦值判斷:判斷當前傳入的實例和原*this指針指向實例是不是同一個,若是一個,則不能進行自賦值(在賦值結束釋放原有空間時,新傳入參數的內存也被釋放,造成賦值失敗)
程序1.0:
考慮到以上幾點,寫出如下
CMyString&operator=(const CMyString&c) { if (this != &c)//檢查自賦值,若存在自賦值,在析構的時候會被析構兩次,出現錯誤 { delete[]m_pData;//釋放原有內存資源 int length = strlen(c.m_pData); m_pData = new char[length + 1];//分配新內存 strcpy(m_pData, c.m_pData);//復制 } return *this;//返回本對象的引用(不用再臨時拷貝一份) }
程序2.0
在考慮以上幾點的同時,考慮異常安全性的解法
CMyString&operator=(const CMyString&c) { if (this != &c) { CMyString StrTmp(c); char *tmp = StrTmp.m_pData; StrTmp.m_pData = m_pData; m_pData = tmp; } return *this; }
在這個新函數中,我們只要創建一個臨時的實例,把這個實例的m_pData和臨時創建的實例的m_pData做交換。由于新創建的實例是臨時變量,在出了作用域后自動調用析構函數析構,釋放零時實例的內存(這樣就釋放了這個實例的m_pData指向的內存)
在構造函數中,用new開辟空間,若開辟失敗則拋出bad_alloc異常,由于我們在構造時還未修改原來實例的狀態,故實例的狀態還是有效的,故保證了異常安全性。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。