[英]Assignment Operator for Doubly Linked List C++
我一直無法讓我的賦值運算符使雙向鏈接列表正常工作。 當rhs是一個空列表時,該操作符可以正常工作,但是如果填充了該操作符,則該操作符將不起作用,並拋出異常錯誤,指出“讀取訪問沖突” 。
這是我的主程序,將不會運行。
#include <cstdlib>
#include "linkedlist.h"
using namespace std;
int main()
{
LinkedList e1;
e1.insertToFront("A");
e1.insertToFront("B");
e1.insertToFront("C");
LinkedList e2;
e2.insertToFront("Please work");
e1 = e2; //Expecting e1 to now just hold "Please work".
system("pause");
}
這是賦值運算符本身(在單獨的頭文件中)。
// assignment operator
const LinkedList& LinkedList::operator=(const LinkedList& rhs)
{
Node* temp;
temp = head;
Node* forward;
forward = new Node;
while (temp != nullptr) // clear memory of target variable
{
forward = temp->next;
delete temp;
temp = forward;
}
if (rhs.head == nullptr)
{
head = nullptr;
tail = nullptr;
}
//GOOD THROUGH THIS PNT.
else
{
temp = rhs.head;
while (temp != nullptr)
{
this->addToEnd(temp->value);
temp = temp->next;
}
}
return *this;
}
這是我調用的addToEnd函數以及Node結構。
void LinkedList::addToEnd(const ItemType& val)
{
Node* temp;
temp = new Node;
temp->value = val;
if (this->head == nullptr)
{
head = temp; // make new node head if list is empty
head->next = nullptr;
head->prev = nullptr;
tail = temp;
}
else
{
temp->prev = tail; // otherwise point current tail towards temp
temp->next = nullptr;
tail->next = temp;
tail = temp;
}
return;
}
////////////////////////////////////////////////////////////////////////
struct Node
{
ItemType value;
Node* next;
Node* prev;
};
您刪除了舊節點,但是忽略了將head
和tail
設置為nullptr
,因此這些指針仍然指向已刪除的對象。 然后,您嘗試將元素添加到該已刪除列表中,並獲得未定義行為。
當清除現有節點時,在開始從源列表中復制值之前,無需將head
和tail
指針重置為nullptr
。 因此,您正在使用無效的指針將新的Node
添加到列表中。
您還存在少量內存泄漏,因為您正在為forward
變量分配新的Node
,然后如果源列表不為空,則立即重新分配forward
以指向另一個Node
。 您永遠不會使用new
delete
分配的Node
。 清除現有節點時,您不應分配任何資源。
為了使事情更安全一些,您應該將列表的清除內容包裝在其自己的單獨方法中,然后可以在需要時調用該方法(不要忘了在析構函數中,而不僅僅是在operator=
)。
如果您使用copy-and-swap習語按照復制構造函數(確實有一個,對嗎?)實現賦值operator=
會更好。 並且由於您顯然使用的是C ++ 11或更高版本,因此還應該實現move構造函數。 這些步驟將大大簡化您的operator=
實施並使其更安全。
嘗試這個:
class LinkedList
{
public:
LinkedList() = default;
LinkedList(const LinkedList& src);
LinkedList(LinkedList&& src);
~LinkedList();
...
LinkedList& operator=(LinkedList rhs);
...
private:
Node *head = nullptr;
Node *tail = nullptr;
...
};
#include <utility>
LinkedList::LinkedList(const LinkedList& src)
{
Node* temp = src.head;
while (temp)
{
addToEnd(temp->value);
temp = temp->next;
}
}
LinkedList::LinkedList(LinkedList&& src)
: head(src.head), tail(src.tail)
{
src.head = src.tail = nullptr;
}
LinkedList::~LinkedList()
{
clear();
}
void LinkedList::clear()
{
Node *temp = head;
head = tail = nullptr;
while (temp)
{
Node *forward = temp->next;
delete temp;
temp = forward;
}
}
LinkedList& LinkedList::operator=(LinkedList rhs)
{
std::swap(head, rhs.head);
std::swap(tail, rhs.tail);
return *this;
}
您還可以insertToFront()
簡化insertToFront()
和addToEnd()
方法:
struct Node
{
ItemType value;
Node* next = nullptr;
Node* prev = nullptr;
Node(const ItemType& val) : value(val) {}
};
void LinkedList::insertToFront(const ItemType& val)
{
Node* temp = new Node(val);
if (!tail)
tail = temp; // make new node tail if list is empty
if (head)
{
temp->next = head; // point current head towards temp
head->prev = temp;
}
head = temp;
}
void LinkedList::addToEnd(const ItemType& val)
{
Node* temp = new Node(val);
if (!head)
head = temp; // make new node head if list is empty
if (tail)
{
temp->prev = tail; // point current tail towards temp
tail->next = temp;
}
tail = temp;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.