我目前正在研究名为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
任何提示或建议将不胜感激。如果需要其他任何东西,请告诉我。
答案 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
}
}
这有效,我相信它是无内存泄漏的。