0

我目前正在开发一个名为 Text 的 ADT,并且正在重载赋值运算符。当我像这样测试运算符时:assignText = alpha一切正常。但是,当我这样做时,会assignText = assignText输出两个实心条。

assignText 被声明为一个 Text 对象。

我的重载赋值运算符如下:

void Text::operator= (const Text& other) { 
bufferSize = other.getLength();
buffer = new char[bufferSize];
buffer = other.buffer; 
}

地点int bufferSize和地点char *buffer

任何提示或建议将不胜感激。如果还需要什么,请告诉我。

4

6 回答 6

1

这是内存泄漏。您将两个不同的指针分配给buffer.

 buffer = new char[bufferSize];
 buffer = other.buffer; 
于 2012-09-08T21:25:08.923 回答
1

关于手头的问题,C++ 常见问题解答中涵盖了这一点:“我为什么要担心“自赋值”?” . 首先阅读常见问题解答通常是一个好主意。或者至少略读一下。

当您绝对必须实现复制赋值运算符时,通常复制和交换习语就足够了。它也是异常安全的。像这样:

void swapWith( MyType& other ) throw()
{
    // swap them members
}

void operator=( MyType other )
{
    swapWith( other );
}

在这里,复制构造函数创建了形式参数副本,并且任何异常都发生在那里,因此复制构造函数也集中了在复制失败的情况下的清理。之后交换两个对象的内容,复制对象的析构函数负责清理该对象的内部内容。结果void类型还不是传统的,但正如我所见,浪费代码和时间来支持具有副作用的表达式是不明智的,这是邪恶的。

现在,你可以避免这一切,只需使用std::vector你的缓冲区。

所以这就是我推荐的,真正简单的解决方案:使用std::vector.

于 2012-09-08T21:26:08.627 回答
1

其他答案已经指出了您的运营商实施的各种问题。在这里,我将尝试了解您正在发生的事情,即为什么代码的行为与您观察到的一样。如果this == &other,即在自分配期间,您将当前长度作为新缓冲区的大小。该新缓冲区未初始化,因此此时它可能包含随机字节。在自我分配的情况下,最后一个分配是无操作的。总结一下:

void Text::operator= (const Text& other) { 
  bufferSize = other.getLength(); // Take length from current object
  buffer = new char[bufferSize];  // Create new buffer, old buffer turns into a memory leak
  buffer = other.buffer;          // No-op as both are the same variable
}

所以这告诉你的是你最终得到了一个当前对象大小但内容未定义的缓冲区。在您的情况下,未定义的内容恰好代表您提到的垂直条。

要解决此问题,请确保根据其他答案和评论的建议修复赋值运算符。

于 2012-09-08T22:47:08.867 回答
0

这是因为您的赋值运算符根本上是不安全的。您需要打破旧状态作为最后一步。考虑

Text& Text::operator= (const Text& other) {
    auto new_buffer = new char[other.bufferSize];
    std::copy(other.buffer, other.buffer + other.bufferSize, new_buffer);
    // Now consider whether or not you need to deallocate the old buffer.
    // Then set the new buffer.
    buffer = new_buffer;
    bufferSize = other.bufferSize;
    return *this;
}

这确保了如果遇到任何问题,可以保证Text对象始终有效——并且作为奖励,它是自分配安全的。所有编写良好的赋值运算符都是自赋值安全的。

这通常与复制和交换联系在一起,复制然后交换——保证安全。

于 2012-09-08T21:26:21.193 回答
0

这段代码将完美运行

Text& Text::operator=(const Text& other) 
{ 
    if(this == &other) /* checks for self assignment */
         return *this;

    if(NULL == other.buffer)
         return *this;

    if(NULL != buffer) /* assuming buffer=NULL in constructor */
    {
         delete [] buffer;
         buffer = NULL;
    }

    bufferSize = other.getLength();
    buffer = new char[bufferSize+1];
    memset(buffer, 0, bufferSize+1);
    memcpy(buffer, other.buffer, bufferSize);

    return *this;
}

试试这个..

于 2012-09-10T11:28:51.767 回答
0

经过一番思考和回顾,我想我明白了。鉴于我需要编写一个由头文件指示的 void 函数,我必须从中构造我的实现。我考虑了 Drew Dormann、MvG 以及其他人的评论,得出了这个结论:

void Text::operator= (const Text &other) 
{ 
    if (this != &other) // takes care of self-assignment
    { 
         delete [] buffer; // delete the old buffer
         bufferSize = other.bufferSize; // assign size variable
         buffer = new char[bufferSize + 1]; // create new buffer
         strcpy(buffer, other.buffer); // copy array
    }
}

这行得通,我相信它没有内存泄漏。

于 2012-09-10T16:15:11.973 回答