繁体   English   中英

单链接列表中的重载operator =

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM