【问题标题】:Overloading operator new / allocate more than object size重载运算符 new / 分配超过对象大小
【发布时间】:2013-03-05 22:54:53
【问题描述】:

我正在尝试重载我的类的运算符 new,我想为对象的属性和类中未定义的字符向量分配空间。

但是当我实例化一个新对象时,先前对象的字符正在改变。 我做错了吗?

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

【问题讨论】:

  • 请添加语言标签
  • 你能说明你是如何测试这个的吗?
  • @BrunoGouveia:我怀疑你的 operator new 根本没有被调用...但是没有看到它的测试代码,我不能肯定地说。
  • char&amp; String::operator [ ](int); 使引用计数字符串成为一个坏主意。
  • @MooingDuck:如果引用计数的字符串实现了写时复制语义,例如在非 const [] 运算符中,它们的效果会很好。如果修改操作检测到字符串的引用计数大于 1,它可以分配引用计数为 1 的有效负载的新副本,更新字符串以指向该新有效负载,并减少前一个有效负载的引用计数所以其他字符串不受影响。

标签: c++ operator-overloading new-operator


【解决方案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);

一旦我知道有关如何测试的评论的答案,我将返回对此答案的编辑。

【讨论】:

  • 准备好了,我添加了我的测试方式。
  • 等等,this + sizeof(*this)this + 12 都错了不是吗?对于数组迭代之类的,那些不是将this 指向的对象的大小提高 12 倍吗?
  • @Mooing Duck:是的,得出了同样的结论(只是花了我一点时间......)
  • 这段代码是我老师写的……他在课堂上写的,我们要继续部署课堂。这是一个非常天真的错误,这是我第一次看到重载 new 运算符。谢谢你们......我把我的下午都浪费在了这件事上。呸呸呸
  • 嗯,很明显,要么你把代码抄错了,要么你的老师写得不好……不幸的是,这是一个容易犯的错误,但要找到一个却很难。 .
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多