2011-12-06 9 views
1

更新:str1の新しいデータ用に割り当てられたメモリ。メモリエラーです。書き換え+ =演算子C++

作成した文字列クラスに対して+ =メソッドを書き直そうとしています。

メインクラスで次に
Class mystring{ 

public: 
    friend void operator+=(mystring& str1, const mystring& str2){ 
     mystring temp; 

     delete[] temp.data; 
     temp.length = str1.length + str2.length; 
     temp.data = new char[temp.length + 1]; 

     strcpy(temp.data, str1.data); 
     strcat(temp.data, str2.data); 

     delete[] str1.data; 
     str1.length = temp.length; 

     strcpy(str1.data, temp.data); 

    } 

private: 
    char *data; 
    int length; 

} 

:それがあるべきよう

mystring str1("hi"); 
mystring str2("matt"); 

str1 += str2; 
cout << str1 << endl; 

この機能が働いているが、私はvalgrindのを実行したときに私はすべての上にメモリエラーを取得しています。私はそれがなぜあるのか理解できません。もし誰かが私にすごくすばらしいヒントを与えることができたら。あなたはstr1に追加のメモリを割り当てる必要があり

おかげ

+0

は、なぜあなたは、車輪を再発明していますか? – SLaks

+1

valgrindに表示されている関連エラーとコンストラクタコードを入れてください。 – Arunmu

+0

スワップメソッドを定義する必要があることに注意してください。最初にtemp.dataを削除する必要がないように、おそらく特別なミストルのコンストラクタが必要です。あなたは長さを知っているのでmemcpyを使うべきです:strcpyとcatは無駄です。 tempを作成した後のスワップメソッドでは、新しい文字列をスワップするだけです(* this、temp)。スワップはポインタと長さを入れ替えるだけです。 –

答えて

2

まず、あなたはありません意味:

strcat(str1.data, str1.data); 

しかし:

strcat(str1.data, str2.data); 

を第二に、どこにstr2.dataが行くことを期待していますか?それは記憶の書き起こしであり、したがってvalgrindの誤りです。驚いただけではクラッシュしません。

新しいストレージに再割り当てする前に、結合された長さに十分なストレージを再割り当てし、元の文字列をコピーしてstr1.dataを解放する必要があります。更新ポストに基づいて

friend void operator+=(mystring& str1, const mystring& str2) 
    { 
     // Not using a temp mystring here, as the temp never really maintains its state as a mystring 
     // I am assuming length is the length of the string, not the storage. Not the best design if you consider resizing the the string to less than the storage 
     int newStringLength = str1.length + str2.length; 
     char* newStorage = new char[newStringLength + 1]; 

     strcpy(newStorage, str1.data); 
     // strcat has to scan from the start of the string; we do not need to. 
     strcpy(newStorage + str1.length, str2.data); 

     delete[] str1.data; 

     str1.length = newStringLength ; 
     str1.data = newStorage; 

     // Haven't though about the case where str2 is an alias for str1. 
    } 
+0

返事をありがとう。あなたのメソッドを使うようにコードを変更しましたが、まだメモリエラーが出ています。 OPが更新されました。 – KWJ2104

+0

"str2がstr1のエイリアスの場合については考えていない。" - 's + = s;'を実行すると何が問題になるのでしょうか? 's'は元の文字列を2回繰り返しただけです。 – visitor

+0

@visitor。その価値のチェックを意味するとは考えていませんでした。すぐに読んでみると、これは問題ないだろうと私に示唆していますが、エイリアスのケースでのみ破損する代替実装については簡単に考えることができます。 – Keith

2

アレイの最後を盲目的にコピーすることはできません。

1

文字を保持するためにヒープを割り当て、必要がなくなったらヒープを解放する必要があります。このような

何か:

data=new char[length+1]; 
1
//it is strange that operator += return void 
// usually we have T& operator += (T const&, T const&) 
    //or T& T::operator +=(T const&) 
friend void operator+=(mystring& str1, const mystring& str2){ 
    //make sure str1 and str2 are correclty initialzed 
    str1.length = str1.length + str2.length; 
    //make sure str1.data has enough memory to hold all the data 
    //make sure str1.data and str2.data are null terminated strings, not binary data 
    strcat(str1.data, str2.data); 
}