2015-10-29 92 views
1

我正在爲自己的作業定義自己的字符串類。這涉及到我的注意,下面的代碼在C++中連接兩個自定義的字符串對象?

class MyString { 
public: 
    MyString(const char* s = NULL) {len = strlen(s); str = new char[len + 1]; strcpy(str, s);} 
    ~MyString() {delete [] str;} 
    friend ostream& operator << (ostream& ost, const MyString& s) { ost << s.str; return ost;} 
    friend MyString operator + (const MyString &s1, const MyString &s2) { 
     int length = strlen(s1.str) + strlen(s2.str); 

     char *str = new char[length + 1]; 
     strcpy(str, s1.str); 
     strcat(str, s2.str); 
     return MyString(str); 
    } 
private: 
    char * str; 
    int len; 
}; 

int main() { 
    MyString s1 = MyString("hello"); 
    MyString s2 = MyString("world"); 
    cout << s1 + s2 << endl; 
    return 0; 
} 

作品,返回的對象是在最後時刻產生。但下面的代碼

class MyString { 
public: 
    MyString(const char* s = NULL) {len = strlen(s); str = new char[len + 1]; strcpy(str, s);} 
    ~MyString() {delete [] str;} 
    friend ostream& operator << (ostream& ost, const MyString& s) { ost << s.str; return ost;} 
    friend MyString operator + (const MyString &s1, const MyString &s2) { 
     int length = strlen(s1.str) + strlen(s2.str); 
     MyString temp; 
     temp.str = new char[length + 1]; 
     strcpy(temp.str, s1.str); 
     strcat(temp.str, s2.str); 
     return temp; 
    } 
private: 
    char * str; 
    int len; 
}; 

int main() { 
    MyString s1 = MyString("hello"); 
    MyString s2 = MyString("world"); 
    cout << s1 + s2 << endl; 
    return 0; 
} 

不,給我一個運行時錯誤。所以我很困惑爲什麼第二種方法失敗,如果一個臨時對象被定義,修改並在重載操作符中返回。

+0

我強烈推薦兩件事:(1)不要使用手動記憶管理;相反,環繞一個'std :: unique_ptr '。 (2)不要使用C字符串函數。使用C++標準庫算法代替(特別是,這將是'std :: copy'這裏。 –

+3

'MyString temp;'使用's == nullptr'的構造函數,然後'strlen(s)'是UB。 – zch

+1

請使用debugger – Drop

回答

0
在構造函數

你分配你的內存爲您的字符串:

len = strlen(s); str = new char[len + 1]; strcpy(str, s); 

所以如果你追加一個字符串以後;因此沒有分配內存。

創建兩個字符串的總和時;你創建你的「和字符串」是這樣的:

MyString temp; 

然後爲str分配的內存是未知的;因爲

len = strlen(NULL); 

如果你想繼續;你可能會考慮增加兩件事:

  • a檢查s = NULL;然後不分配內存,但這會在稍後造成麻煩...
  • 分配更多內存的方法;像temp.allocate(strlen的(S1)+ strlen的(S2))
3

的問題是,當你默認,構建temp這裏:

MyString temp; 

,你必須執行:

MyString(const char* s = NULL) {len = strlen(s); ... } 

strlen空指針未定義。如果你不是改變了默認參數,將工作:

MyString(const char* s = "") 

然而,這兩種解決方案仍然較差,它們都泄漏內存。在前者中,你永遠不會delete[]臨時str。在後者中,您的默認構造函數分配了一個新的str成員,然後您立即用新分配的str成員覆蓋它。原稿被泄露。

0

返回創建一個對象並複製指針。然後在同一地址發生2次刪除