2

クラスの新しい演算子をオーバーロードしようとしています。オブジェクトの属性と、クラスで定義されていない文字のベクトルにスペースを割り当てたいと思います。

しかし、新しいオブジェクトをインスタンス化すると、以前のオブジェクトの文字が変更されます。私は何か間違ったことをしていますか?

class StringData
{       
public:
    friend class String;
    int refCount;
    int len;
    int maxLen;
    ~StringData()
    {

    }
    StringData()
    {
        maxLen = 1000;
        len = 0;
        refCount = 1;
    }
    StringData(const char * string)
    {
        maxLen = 1000;
        char * data = buffer();

        len = 0;
        while (string[len] != '\0' && len < (maxLen - 1))
        {
            data[len] = string[len];
            len++;
        }
        data[len] = '\0';
        refCount = 1;
    }
    char* buffer()
    {
        return reinterpret_cast<char*>(this + 12);
    }

public:
    void* operator new(size_t size, int maxLen)
    {

        return ::operator new(size + round4(maxLen + 1));

    }
    static int round4(int len)
    {
        return ((((int) (len / 4)) + 1) * 4);
    }

    void operator delete(void* obj)
    {
        ::operator delete(obj); 
    }
    void operator delete(void* obj, int size) throw ()
    {
        ::operator delete(obj); 
    }
};

私はこれを他のクラスで使用します:

class String{
public:
    StringData * data;

    String(StringData * data){
        this->data = data;
    }
public:
    String(const char*);
    String(const String&);
    ~String();
    String& operator =(const String);
    String& operator =(const char *);
    int length() const;
    bool operator ==(const String&) const;
    int compare(const String&) const;
    bool operator ==(const char*) const;
    int compare(const char*) const;
    String& operator +(const String&) const;
    String operator +(const char*) const;
    String operator +=(const String&);
    String operator +=(const char*);
    String toLower();
    String toUpper();
    char operator [ ](int) const;
    char& operator [ ](int);
    void print() const;

};

String::String(const char * string){
int stringLen = 0;

while (string[stringLen] != '\0')
    stringLen++;

data = new (stringLen + 1) StringData(string);

}

String::String(const String& string){

data = string.data;
string.data->refCount++;

}

String::~String(){
this->data->refCount--;
if (this->data->refCount == 0)
    delete data;

}

String& String::operator=(const String string){
data->refCount--;
if (this->data->refCount == 0)
    delete data;
data = string.data;
string.data->refCount++;
return *this;

}

void String::print() const{ printf("%s\n", data->buffer()); }

そして私の主な機能は次のとおりです。

int main(){
String *a = new String("boisahzashdacaraverdeepretaeazuleamarelaecinzaevermelha");
a->print();
String * s = new String("freestepehnoisquevoaashashashhasshashhasssasassadasd");
String * b = new String("kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk");

a->print();
s->print();
return 0;

}

実行すると、文字列が壊れます。

boisahzashdacaraverdeepretaeazuleamarelaecinzaevermelha

boisahzashdacaraverd

freestepehnoisquevoa

4

1 に答える 1

1

これは素晴らしいアイデアではありません。

return reinterpret_cast<char*>(this + 12);

一部のメンバー関数を追加/削除した場合(または仮想関数を作成した場合)に失敗するだけでなく、のサイズにも依存しintます。

使用する

return reinterpret_cast<char*>(this) + sizeof(*this);

[reinterpret_cast <>()!!の終わりの新しい配置に注意してください]最初のバージョンは、バイト12 * sizeof(*this)ではなく、前方にスキップします。12[もちろん、私のマシンでは、maxLenの4 *乗数を使用すると、実際に機能します。それを削除したときにのみ失敗し始めました]

これは単純化できます。

((((int) (len / 4)) + 1) * 4);

これはmaxlenの4倍になると思われますか?

(4 * maxLen)

に:

4 * (len / 4 + 1);

テスト方法に関するコメントへの回答がわかったら、この回答の編集に戻ります。

于 2013-03-05T23:56:38.143 に答える