簡體   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