[英]Overloading operator= in a singly linked list
我目前在将内容从一个列表复制到另一个列表时遇到问题。 编译时,所有值均显示为0。 我认为,当复制构造函数正在使用其代码时,重载赋值运算符可能会出问题。
复制构造函数
ListOfDoubles::ListOfDoubles(const ListOfDoubles&e):head(NULL) {
if (this != &e) {
*this = e;
}
}
重载运算符=
const ListOfDoubles& ListOfDoubles::operator=(const ListOfDoubles
&doubleslist)
{
DoubleListNode *cpyPtr = NULL;
DoubleListNode* orgPtr = doubleslist.head;
if (this != &doubleslist)
{
while (head != NULL)
{
ListOfDoubles::~ListOfDoubles();
}
while (orgPtr != NULL)
{
if (head == NULL)
{
head = cpyPtr = new DoubleListNode(orgPtr->data);
}
else
{
cpyPtr->next = new DoubleListNode(orgPtr->data);
cpyPtr = cpyPtr->next;
}
orgPtr = orgPtr->next;
}
}
return *this;
}
通用复制逻辑如下所示:
DoubleListNode * from = source.head; // copying from
DoubleListNode ** to = &head; // pointer to where we want to copy to
while (from != nullptr) // keep going until end of list. You did mark
// the end of the list, didn't you?
{
*to = new node(*from); //copy construct a new node around from and store it at to
to = &(*to)->next; // advance to
from = from.next; // advance from
}
*to = nullptr; // all done. Terminate list.
真正的魔力在这里出现在双指针处: DoubleListNode ** to
通过拥有一个指向指针的指针,我们不在乎我们是指向head
,另一个节点的next
一个节点还是拥有什么。 它只是另一个节点,因此没有特殊情况需要讨论。
您可以在复制构造函数和赋值运算符中执行上述操作,尽管最好不要重复自己,并将其放入复制构造函数和赋值运算符调用的函数中。 请注意,对于复制构造函数中的现有数据(例如,列表将为空)和赋值运算符(例如,列表可能不为空,因此请清除它并在开始之前释放所有节点)有不同的假设:需要考虑在内。
如上面的评论所述,主要的替代方法是使用Copy and Swap Idiom 。 为此,上述复制循环仅存在于复制构造函数中。
复制构造函数的输入参数永远不会是要构造的对象,因此在复制构造函数中检查this != &e
是多余的。
此外,除非使用不使用的placement-new
分配内存,否则直接手动调用析构函数是非法的。 您需要使用delete
销毁您的节点实例。
通常,不应以operator=
形式实现复制构造函数,而应采用其他方法。 让复制构造函数完成复制源值的工作,然后让operator=
复制源列表并获得复制数据的所有权。 这通常称为“复制和交换”习惯用法。
尝试以下方法:
ListOfDoubles::ListOfDoubles()
: head(NULL)
{
}
ListOfDoubles::ListOfDoubles(const ListOfDoubles &e)
: head(NULL)
{
DoubleListNode *cpyPtr = NULL;
DoubleListNode *prevPtr = NULL;
DoubleListNode *orgPtr = e.head;
while (orgPtr)
{
cpyPtr = new DoubleListNode(orgPtr->data);
if (!head)
head = cpyPtr;
if (prevPtr)
prevPtr->next = cpyPtr;
prevPtr = cpyPtr;
orgPtr = orgPtr->next;
}
/* alternatively:
DoubleListNode **cpyPtr = &head;
DoubleListNode *orgPtr = e.head;
while (orgPtr)
{
*cpyPtr = new DoubleListNode(orgPtr->data);
cpyPtr = &((*cpyPtr)->next);
orgPtr = orgPtr->next;
}
*cpyPtr = NULL;
*/
}
ListOfDoubles::~ListOfDoubles()
{
DoubleListNode *orgPtr = head;
DoubleListNode *nextPtr;
while (orgPtr)
{
nextPtr = orgPtr->next;
delete orgPtr;
orgPtr = nextPtr;
}
}
ListOfDoubles& ListOfDoubles::operator=(const ListOfDoubles &doubleslist)
{
if (this != &doubleslist)
{
ListOfDouble tmp(doubleslist);
std::swap(head, tmp.head);
}
return *this;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.