【发布时间】:2020-06-26 11:03:33
【问题描述】:
我正在做一个带有哨兵节点的双向链表,使双向链表成为一个循环列表(没有指向前后的头和尾指针,相反,头由 m_sentinel->m_next 和tail 由 m_sentinel->m_prev 引用)。下面是代码:
在 MyList.h 中:
template <typename T>
class Node
{
public:
T m_element;
Node<T> *m_prev;
Node<T> *m_next;
// Helps make a dummy/sentinel/junk node
Node(Node<T> *in_prev, Node<T> *in_next):
m_prev(in_prev), m_next(in_next){}
Node(const T &x, Node<T> *in_prev, Node<T> *in_next):
m_element(x), m_prev(in_prev), m_next(in_next){}
};
template <typename T>
class MyList
{
private:
Node<T> *m_sentinel = nullptr;
int m_size;
public:
MyList();
~MyList();
MyList<T> & operator=(const MyList<T> &source);
void clear();
void push_back(const T &x);
在 MyList.hpp 中:
template <typename T>
MyList<T>::MyList()
{
m_size = 0;
m_sentinel = new Node<T>(NULL, NULL);
}
template <typename T>
MyList<T>::~MyList()
{
clear();
m_size = 0;
}
template <typename T>
MyList<T> & MyList<T>::operator=(const MyList<T> &source)
{
if(this == &source)
{
return *this;
}
while(source.m_sentinel->m_next != source.m_sentinel)
{
Node<T> *temp = source.m_sentinel->m_next;
push_back(temp->m_element);
source.m_sentinel->m_next = temp->m_next;
}
return *this;
}
template <typename T>
void MyList<T>::clear()
{
if(m_sentinel->m_prev == NULL && m_sentinel->m_next == NULL)
{
delete m_sentinel;
}
else
{
int k = size();
for(int i = 0; i < k; i++)
{
pop_back();
}
delete m_sentinel;
}
}
template <typename T>
void MyList<T>::push_back(const T &x)
{
Node<T> *newNode;
newNode = new Node<T>(x, NULL, NULL);
if(m_sentinel->m_prev == NULL && m_sentinel->m_next == NULL)
{
newNode->m_prev = m_sentinel;
newNode->m_next = m_sentinel;
m_sentinel->m_prev = newNode;
m_sentinel->m_next = newNode;
}
else
{
newNode->m_next = m_sentinel;
newNode->m_prev = m_sentinel->m_prev;
Node<T> *temp = newNode->m_prev;
m_sentinel->m_prev = newNode;
temp->m_next = m_sentinel->m_prev;
}
m_size++;
}
在 main.cpp 中:
#include "MyList.h"
int main()
{
MyList<int> x;
x.push_front(1);
x.push_front(2);
x.push_front(3);
x.push_front(4);
x.push_front(5);
x.push_front(6);
x.push_front(7);
MyList<int> p;
p = x;
// Below just outputs each linked list
int j = 0;
int m = x.size();
cout << endl << endl;
for(auto i = 0; i < m; i++)
{
cout << x.front() << endl;
x.pop_front();
j++;
}
cout << endl << endl;
j = 0;
m = p.size();
for(auto i = 0; i < m; i++)
{
cout << p.front() << endl;
p.pop_front();
j++;
}
cout << endl << endl;
运行此代码时,x 确实被成功复制到 p。输出 p 时,给出以下输出:7 6 5 4 3 2 1,但输出 x 时,给出以下输出:-19823746 ... 这只是垃圾内存值(这告诉我 x 显然正在改变,但 p 成功获取 x 的内容)。我不知道它为什么会改变;我正在寻找赋值运算符的修复/解决方案,因为它无法正常工作。
【问题讨论】:
-
您的用户定义的复制构造函数在哪里?即使你让赋值运算符工作,你的类仍然被破坏,并且通过在
main函数中执行MyList<int> p = x;很容易破坏。阅读the rule of three -
我打算在赋值运算符之后处理复制构造函数 - 坏主意?不过我会检查那个链接,谢谢!
-
最好的方法是先处理复制构造函数和析构函数。不理会赋值运算符。然后,当您可以使复制构造函数和析构函数正常工作时,赋值运算符大约需要两分钟才能使用copy / swap 成语正确编码。
-
{MyList<T> t = source; std::swap(t.m_size, m_size); std::swap(t.m_sentinel, m_sentinel); return *this;}-- 信不信由你,那将是赋值运算符如果您首先编写了复制构造函数和析构函数。 -
然后自己交换物品。这就是
std::swap所做的一切。请阅读有关复制和交换的链接。您所做的就是将临时变量内容换成当前内容,然后让临时变量消失。
标签: c++ linked-list operator-overloading doubly-linked-list assignment-operator