C ++ Assignment重载自我分配问题

时间:2012-09-08 21:17:47

标签: c++ pointers operator-overloading

我目前正在研究名为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 bufferSizechar *buffer

的位置

任何提示或建议将不胜感激。如果需要其他任何东西,请告诉我。

6 个答案:

答案 0 :(得分:1)

这是内存泄漏。您正在为buffer分配两个不同的指针。

 buffer = new char[bufferSize];
 buffer = other.buffer; 

答案 1 :(得分:1)

关于手头的问题,这是C ++ FAQ所涵盖的:"Why should I worry about "self assignment"?"。首先阅读常见问题解答通常是个好主意。或者至少略过它。

当您必须实现复制赋值运算符时,通常复制和交换习惯用法就足够了。这也是例外的安全。是这样的:

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

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

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

现在,可以避免所有这些,只需使用std::vector作为缓冲区。

这就是我推荐的,非常简单的解决方案:使用std::vector

答案 2 :(得分: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
}

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

要解决此问题,请务必根据其他答案和评论中的建议修复作业运算符。

答案 3 :(得分:0)

这是因为您的赋值运算符从根本上说是不安全的。您需要将旧状态作为 last 步骤中断。考虑

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对象始终有效 - 并且作为奖励,是自我分配安全的。所有编写良好的赋值运算符都是自我赋值安全的。

这通常与复制和交换相关联,复制和交换,然后交换 - 保证安全。

答案 4 :(得分: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;
}

试试这个..

答案 5 :(得分: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
    }
}

这有效,我相信它是无内存泄漏的。