检测到堆腐败

时间:2011-03-28 18:36:13

标签: c++ string overloading operator-keyword

关于我的程序输出唯一不正确的是,有一个'!' '钓鱼'之后。我试过调试它,但从来没有'!'在记忆中。

以下是此行的输出

One more: gone down to the fishing! hole

这是s6和s7的创建

MyString s6("gone ");
MyString s7("fishing");

以下是生成语句

的行
cout << "One more: " << s6 + "down to the " + s7 + " hole" << endl << endl;

这是&lt;&lt;操作员过载功能

ostream& operator<<(ostream& leftOp, const MyString& rightOp)
{
leftOp << rightOp.stringArray;

return leftOp;
}

这是+运算符重载函数

MyString MyString::operator+(const char* rightOp) const
{
    MyString result; // new object used to store result
    result.stringSize = stringSize + strlen(rightOp);
    // if the string does not fit in the array
    if( result.stringSize > result.stringCap )
    {
        delete[] result.stringArray;
        result.stringCap = ( stringSize + 15 ) & ~15;
        result.stringArray = new char[stringCap + 1];
    }
    strcpy(result.stringArray, stringArray);
    strcat(result.stringArray, rightOp);
    return result;
}

s7在程序中的任何其他位置都没有被调用,所以我不认为还有其他代码需要显示。任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:3)

很难判断您的代码是否存在问题 我会看看其他成员。 你是否遵守了3 的规则?

注意:

我会指出你违反了一项基本的OO规则。

除非very有充分的理由,否则你不应该操纵另一个对象的成员。 在这里你的对象是摆弄结果。

如果您将代码编写为:

,代码会更清晰
MyString MyString::operator+(const char* rightOp) const
{
    MyString result(*this);   // make a copy of this.
    result += rightOp;        // Let result fiddle with its own members here.
    return result;
}

编辑:

基于以下评论。

Rule of Three

基本上:如果你的对象拥有动态分配的内存(即它调用new / delete),那么编译器生成的方法的默认版本不能按你的意愿工作;你应该定义自己的版本:

基本上:

* Copy Constructor
* Assignment Operator
* Destructor

* Not part of rule of 3, but you probably also need a normal constructor.

简单的事情是你可能已经有了析构函数(否则就不会有损坏),并且可以根据复制构造函数编写赋值运算符。所以你需要做的就是编写一个正确版本的拷贝构造函数,一切都应该有效。

/*
 * Assignment operator using Copy and swap Idiom.
 * Copy uses copy constructor (here done in pass by value)
 *
 * You then just swap the current content with the copy
 */
MyString& MyString::operator=(MyString rhs)
{
    (*this).swap(rhs);
    return *this;
}

答案 1 :(得分:1)

如果你将stringCap分配给你的数组,你介意'\ 0'吗?存储字符串的char *必须是大小为size-of-string + 1

的数组

问题可能是你连续两个MyString。第二个字符串fishing可能有一个太大的stringSize值。

而不是result.stringCap = ( stringSize + 15 ) & ~15;为什么不简单地写:

result.stringCap = result.stringSize + 1;

答案 2 :(得分:0)

您没有在正常情况下分配stringArray,并且您没有在过大的情况下重置stringSize,并且strncpy更安全:

MyString MyString::operator+(const char* rightOp) const
{
    MyString result; // new object used to store result
    result.stringSize = stringSize + strlen(rightOp);
    // if the string does not fit in the array
    if( result.stringSize > result.stringCap )
    {
        delete[] result.stringArray;
        result.stringCap = ( stringSize + 15 ) & ~15;
        // don't allocate here
        result.stringSize = stringCap;
    }

    // always allocate for the new string
    result.stringArray = new char[result.stringSize + 1];

    strncpy(result.stringArray, stringArray, result.stringSize);
    strncat(result.stringArray, rightOp, strlen(rightOp) + 1);
    return result;
}

编辑:好的,不要理会。我假设有关MyString类的某些事情,显然并非如此。所以,这就是我现在可以指出的:

if( result.stringSize > result.stringCap )
{
    delete[] result.stringArray;
    result.stringCap = ( stringSize + 15 ) & ~15;
    result.stringArray = new char[stringCap + 1]; // WRONG stringCap!
    result.stringArray = new char[result.stringCap + 1]; // right stringCap
}

你可以尝试简化问题,缩小问题范围:

cout << "One more: " << s6 + "down to the " << s7 + " hole" << endl << endl;

问题可能在operator+(const MyString&)而不是operator+(const char*)

答案 3 :(得分:0)

if( result.stringSize > result.stringCap )应为if( result.stringSize >= result.stringCap )以允许空终止。您还需要重置result.stringSize