2016-03-27 9 views
3

私は長さを表すintとデータのためにchar*で構造化された文字列クラスに取り組んでいます。C++での自己連結

String s1 = "Hello"; 
s1 += s1; 
cout << s1; 

これが返されます:À$p またはその他の奇妙な文字私は、あなたが、たとえば、自己連結するにはしようとしたときを除いて、うまく動作します+=演算子をオーバーライドしています。関連コードは次のとおりです。

#include <iostream> 
#include <cstring> 
#include "assert.h" 
using namespace std; 

class String{ 
    public: 
    int len; 
    char *str; 

    String() 
    :len(0), str(nullptr){} 

    String(char const* S) 
    :len(strlen(S)), str(new char[len +1]){ 
     assert(S != 0); 
     strcpy(str, S); 
    } 

    ~String(){ 
     delete[]str; 
    } 

    char* data() const{ 
     return this->str; 
    } 

    String operator +=(String const &S){ 
     int n = this->len + S.len; 
     char * p = new char[n+1]; 
     strcpy(p + len, S.str); 
     len = n; 
     str = p; 
     return *this; 
    } 
}; 

std::ostream& operator <<(ostream& os, String const& str){ 
    return os << str.data(); 
} 

int main() 
{ 
    String g1 = "Hello"; 
    g1 += g1; 
    cout << g1; 
    return 0; 
} 
+3

だけ通知を:あなたのコードは、メモリリークが発生します。 –

+1

また、現在のバッファの内容を新しいバッファにコピーしませんでした。 – LogicStuff

+0

あなたは、 '+ ='のオーバーロードに取り組む前にコードを本当に単体テストするべきです。この単純な 'main'関数は' int main(){String s1( "abc");}という問題があることを示しています。 String s2 = s1;} ' – PaulMcKenzie

答えて

5

このコードにはいくつか問題があります。何よりもまず、Rule of Three/Five/Zero isの内容を確認してください。あなたが実際にpに文字列の最初の部分をコピーしていない

  1. は今、実際のoperator+=との三つの問題があります。あなたはちょうど後半をコピーしています。

    memcpy(p, str, len); 
    memcpy(p + len, S.str, S.len); 
    
  2. あなたは古い内容をクリーニングしていません。 str = p;と書くと、strが指していたメモリがリークしたばかりです。その割り当てを行う前に、

    delete [] str; 
    

    とする必要があります。

  3. すぐに破棄される一時的なものを返しています。コピーコンストラクタの不足(最初のポイントを参照)は、結果としてg1のバッファを破棄していることを意味し、delete[]を再度実行すると、main()の末尾にダブルフリーの破損エラーが発生します。この問題は、有効なコピーコンストラクタを書くことによって固定することができますが、operator+=はとにかく、一時帰国してはならない - それは、参照を返すべきである:

    String& operator+=(String const& S) { ... }