C++赋值重载自赋值问题
C++ Assignment overload self-assignment issue
我目前正在开发一个名为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
任何提示或建议都将不胜感激。如果还需要什么,请告诉我。
其他答案已经指出了运算符实现中的各种问题。在这里,我将尝试了解发生了什么,即为什么代码的行为与您观察到的一样。如果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
}
所以这个告诉你的是,你最终得到了一个当前对象大小的缓冲区,但有未定义的内容。在您的案例中,未定义的内容恰好代表您提到的竖条。
要解决此问题,请确保根据其他答案和注释中的建议修复分配运算符。
这是内存泄漏。您正在为buffer
分配两个不同的指针。
buffer = new char[bufferSize];
buffer = other.buffer;
关于手头的问题,C++常见问题解答涵盖了这一点:"我为什么要担心"自分配"?"。首先阅读常见问题解答通常是个好主意。或者至少略读一下。
当您必须实现复制赋值运算符时,通常复制和交换习惯用法就足够了。它也是例外安全的。如下所示:
void swapWith( MyType& other ) throw()
{
// swap them members
}
void operator=( MyType other )
{
swapWith( other );
}
在这里,复制构造函数创建正式的参数副本,任何异常都会发生在那里,因此在复制失败的情况下,复制构造函数也会集中清理。之后,两个对象的内容被交换,复制对象的析构函数负责清理该对象的内部内容。void
结果类型还不是传统的,但在我看来,将代码和时间都浪费在支持有副作用的表达式上是不明智的,因为副作用是邪恶的。
现在,只需使用std::vector
作为缓冲区,就可以避免所有这些。
这就是我推荐的,真正简单的解决方案:使用std::vector
。
这是因为您的赋值运算符根本不安全。您需要打破旧状态作为最后步骤。考虑
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
对象始终有效,而且作为奖励,它是自分配安全的。所有写得好的赋值运算符都是自赋值安全的。
这通常与复制和交换联系在一起,即复制,然后交换,以确保安全。
这段代码将完美地运行
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;
}
试试这个。。
经过一番思考和审查,我想我明白了。考虑到我需要编写一个由头文件指定的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
}
}
这是有效的,我相信它是无内存泄漏的。
- 为"adjacent"变量赋值时出现问题
- 关于 c++ 函数中指针赋值的简单问题
- 移动赋值运算符;尝试引用已删除的函数.我该如何解决这个问题?
- C++:关于使用 Stroustrup 示例移动构造函数/赋值的问题
- c++问题:给一个变量赋值后,另一个变量发生了变化
- 复制和赋值构造函数的问题
- 类模板的用户定义赋值运算符时遇到问题
- template_back和move赋值构造函数存在问题
- 赋值重载:为什么使用相同的对象会导致程序中出现问题
- C++赋值重载自赋值问题
- 重载赋值运算符的问题
- 交换与使用std::map[]运算符赋值(const问题)
- C++中赋值运算符和 c 字符串的问题
- 在C++中重载赋值运算符时出现问题
- 我在 c++ 中的赋值重载运算符有什么问题?(包括详细信息)
- C++ 向量构造函数和赋值问题
- "无符号长整型"和'unsigned long long int'赋值问题
- 动态分配结构数组:赋值问题(c++)
- c++ OOP初学者,赋值问题
- 奇怪的赋值问题-C++