3

私は文字列クラスの非常に単純な実装を C++ で書き始めました。コードは次のとおりです。

class String
{
public:
    String()
    {
        this->_length = 0;
        this->_size = 0;
        this->_string = NULL;
    }
    String(const char* str)
    {
        this->_length = strlen(str);
        this->_size = this->_length + 1;
        this->_string = new char[this->_size];

        strcpy_s(this->_string, this->_size, str);
    }
    ~String()
    {
        if (this->_string != NULL)
        {
            delete[] this->_string;
            this->_string = NULL;
        }
    }

    String& operator+(const char* str)
    {
        String* temp = new String();

        temp->_length = strlen(str) + strlen(this->_string);
        temp->_size = temp->_length + 1;
        temp->_string = new char[temp->_size];

        strcpy_s(temp->_string, temp->_size, this->_string);
        strcat_s(temp->_string, temp->_size, str);

        return (String&)*temp;
    }

    int Length()
    {
        return this->_length;
    }

private:
    int _size;
    int _length;
    char* _string;
};

私の operator+ の実装は完全に間違っていることがわかります。実際、メモリ リークがあります。char* を this->_string と単純に連結して *this を返すことができるため、operator+= の記述は非常に簡単です。operator+ の実装について助けが必要です。

注:これは宿題なので、コピーアンドペーストで解決したくありませんが、誰かが私を正しい方向に向けることができれば素晴らしいでしょう...

ありがとう

編集:コピーコンストラクターを追加しました:

String(const String& str)
{
    this->_length = str._length;
    this->_size = str._size;
    this->_string = new char[this->_size];
    strcpy_s(this->_string, this->_size, str._string);
}

operator= と operator+=:

String& operator=(const String& str)
{
    if (this != &str)
    {
        this->_length = str._length;
        this->_size = str._size;
        this->_string = new char[this->_size];

        strcpy_s(this->_string, this->_size, str._string);
    }

    return *this;
}
String& operator+=(const String& str)
{
    this->_length = this->_length + str._length;
    this->_size = this->_length + 1;

    char* buffer = new char[this->_size];
    strcpy_s(buffer, this->_size, this->_string);
    strcat_s(buffer, this->_size, str._string);

    delete[] this->_string;
    this->_string = buffer;

    return *this;
}

しかし、次のように while(true) ループを実行すると、まだ何か問題があります。

while (true)
{
    String a = String("string a");
    String b = a;
    b = "string b";
    b += " string c";
}

プロセスによって使用されるメモリは継続的に増加します

4

2 に答える 2

6

operator+=で再利用できますoperator+

operator+=(以下のコードは、コピー コンストラクターと代入演算子があることを前提としていますが、貼り付けたコードには当てはまりません)。

編集: Jerry Coffin によって提案されたように、次の演算子はクラス メンバーではなく、フリー オペレーターであるべきです。

EDIT2:そして、コンパイラがもう少し最適化できるようにするために、最初の引数はconst-referenceではなくなりました:

String operator+(String a, String const &b) {
  a += b;
  return a;
}

これにより、より単純operator+=で単純なコンストラクターをコピーして、単純なものに複雑なものを構築できます。

そして忘れないでください:

コピー コンストラクターと代入演算子を実装する必要があります。そうしないと、コンパイラは間違った方法でそれを生成します。コンパイラは、コンテンツを単にコピーするコードを生成します。したがって、ポインターもコピーしますが、コピーに新しいメモリを割り当てません。次に、同じメモリを参照する 2 つのインスタンスがあり、どちらも未定義の動作であるデストラクタで割り当てを解除しようとします。

于 2013-05-12T20:34:00.590 に答える
3

を実装する簡単な方法の 1 つoperator+は、+=. 左のオペランドのコピーを作成し+=、右のオペランドを追加するために使用し、最後に結果を返します。

また、通常はメンバ関数であってはならないことにも注意してoperator+ください。通常はフリー関数であるべきです。基本的な違いは、メンバー関数として、左側のオペランドが機能するためには既に文字列である必要があることです。フリー関数として、文字列コンストラクターを使用して (たとえば) 文字列リテラルを変換できます。たとえばstring+"something";、メンバー関数では機能しますが、機能し"something" + string;ません。+無料の関数としてオーバーロードすると、両方が機能します。

于 2013-05-12T20:34:23.330 に答える