您好,登錄后才能下訂單哦!
1、為什么我們要學會寫自定義string類
面試官愛考,你有辦法嗎,沒有-.-
2、自定義string類應該如何正確書寫
quote一句c++primer中的話:
類的安全性和處理正確性的不夠,需要類的設計者(也就是我們)去寫拷貝構造和賦值運算符重載函數,而最困難的不是如何書寫而是讓我們自己本身意識到需要這樣做。
關于MyString不得不說的就是:深淺拷貝問題,這個究其原因就是它的成員變量是個char *類型的,如果我們懶到要讓編譯器自己幫我們去建構造、拷貝構造,賦值運算符重載這些函數,那么問題就是很大滴,因為它也很lazy,它做的操作就是讓兩個指針指向同一個地方。
舉個栗子看:
那么下面就說說如何寫一個正確的string:
首先c++中string它是個類對吧
那么我們就寫一個類出來(成員函數和成員變量)
class MyString { private: char *_pData;//對,你沒看錯,只需要一個char型指針就可以實現哦 public: //首先一個類要有構造函數-->保證類的成員變量被正確的初始化 //第一種寫法----正確但不是最優 MyString(char *pData=NULL) { if (pData==NULL) { _pData=new char[1]; _pData[0]='\0'; } else { _pData=new char[strlen(pData)+1]; strcpy(_pData,pData); } } //第二種寫法--比第一種更優:使用初始化列表 MyString(char *pData=NULL) :pData(new char[strlen(pData)+1]) { strcpy(_pData,pData); } //既然在構造中進行了new那么相對的是不是要在析構中去delete? ~MyString() { if (_pData)//這里可以直接不用判斷,think about why? { delete []_pData; } } //拷貝構造-----?為什么需要寫,因為成員變量是指針,如果我們不進行自己去寫 //就會出現安全性和正確性的問題,兩個指針指向一個空間,當其中一個析構后, //另外一個就無法再去訪問這片空間,會出現非法操作 //考點:形參必須傳入的是該類型的引用,不然在實參傳給形參時 //就會發生值傳遞,進行拷貝構造,那么這個拷貝構造就是一個死循環 //第一種寫法 MyString(const MyString &mstr) { if (strlen(mstr._pData)==0) { _pData=new char[1]; _pData[0]='\0'; } else { _pData=new char[strlen(mstr._pData)+1]; strcpy(_pData,mstr._pData); } } //第二種寫法 MyString(const MyString &mstr) :_pData(new char[strlen(mstr._pData)+1]) { strcpy(_pData,mstr._pData); } //第三種寫法:只有在構造和析構的時候開辟和釋放空間,內存空間不易出錯 //不會出現MyString實例化對象的錯誤,考慮到了異常安全性 MyString(const MyString &mstr) :_pData(NULL) //_pData沒有初始化,隨機的空間,如果不賦值為空,會delete失敗 { MyString temp(mstr._pData); swap(temp._pData,_pData); } //賦值運算符重載 //考點:1、返回值是該類型引用(考慮到有連等情況a=b=c) //考點:2、形參是const 引用(不會改變形參并且效率高) //第一種寫法--->缺點:如果在new char[]出錯的話,很有可能_pData就變成野指針 //那么MyString返回的對象就是一個不正確的對象,有異常安全性問題 MyString& operator=(const MyString &mstr) { //考點:3、自己給自己賦值的情況,有沒有考慮到! if (this!=&mstr) { //考點:4、先釋放,一定是釋放[]_pData,原因就是構造的方式 delete []_pData; //再開辟 _pData=new char[strlen(mstr._pData)+1]; strcpy(_pData,mstr._pData); } return *this; } //第二種寫法 MyString &operator=(const MyString &mstr) { //先開辟 char *temp=new char[strlen(mstr._pData)+1]; if (temp==NULL) { return *this; } //在釋放 delete []_pData; _pData=temp; strcpy(_pData,mstr._pData); return *this; } //第三種寫法 MyString &operator=(MyString mstr) { swap(mstr._pData,_pData); return *this; } //更優寫法 MyString &operator=(const MyString &mstr) { if(&mstr!=this) { MyString temp(mstr._pData); swap(temp._pData,_pData); } return *this; } //String對象轉換成const char* const char* C_str()const { return _pData; } //求字符串長度 size_t Size() { return strlen(_pData); } //判斷是否相等 bool operator==(const MyString &mstr)const { if (&mstr!=this) { if(!strcmp(_pData,mstr._pData)) { return false; } } return true; } //某個字符 char operator[](size_t pos)const { if (pos<strlen(_pData)&&pos>=0) { return _pData[pos]; } else { return 0; } } //字符串比較 int operator<(const MyString &mstr)const { int truth=strcmp(_pData,mstr._pData); if (truth>0) { return -1; } else if (truth==0) { return 0; } else { return 1; } } };
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。