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