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