我必须实现这个双向链表。该列表需要一个指向第一个有效元素的前指针和一个指向最后一个有效元素的后指针。
这个代码的问题在于我必须实现T&返回并定义结束迭代器。我目前没有工作
#ifndef List_dllist_h
#define List_dllist_h
#include <iterator>
template <class T>
class DList
{
struct Node
{
Node(const T& x,Node* y = 0):m_data(x),m_next(y),m_prev(y){}
T m_data;
Node* m_next;
Node* m_prev;
};
Node* m_head;
Node* m_back;
public:
class iterator
{
Node* m_rep;
public:
friend class DList;
inline iterator(Node* x=0):m_rep(x){}
inline iterator(const iterator& x):m_rep(x.m_rep) {}
inline iterator& operator=(const iterator& x)
{
m_rep=x.m_rep; return *this;
}
inline iterator& operator++()
{
m_rep = m_rep->m_next; return *this;
}
inline iterator operator++(int)
{
iterator tmp(*this); m_rep = m_rep->m_next; return tmp;
}
inline iterator& operator--()
{
m_rep= m_rep->m_prev; return *this;
}
inline iterator operator--(int)
{
iterator tmp(*this); m_rep= m_rep->m_prev; return tmp;
}
inline T& operator*() const { return m_rep->m_data; }
inline Node* operator->() const { return m_rep; }
inline bool operator==(const iterator& x) const
{
return m_rep == x.m_rep;
}
inline bool operator!=(const iterator& x) const
{
return m_rep != x.m_rep;
}
};
DList() : m_head(0), m_back(0) {}
~DList() { clear(); }
inline T& front() { return *begin(); }
inline const T& front() const { return *begin(); }
inline T& back() { return *--end(); }
inline const T& back() const { return *--end(); }
inline iterator begin() { return iterator(m_head); }
inline iterator end() { return iterator(m_back); }
};
#endif
编辑:添加--operator
答案 0 :(得分:1)
back()
迭代器的问题比起初看起来要复杂一些。 back()
与end()
密切相关,但您的end()
实施无法正常运作,我稍后会解释。您的迭代器类实际上并不是设计为非常好地表示end()
值,因为它是当前编写的。
但是,让我们暂时假装你的end()
迭代器很好而且很好。如果是这种情况,您的back()
可以简写为:
inline T& back() { return *--end(); }
这是back()
的经典定义。就是这样。 const
版本将是类似的。
您尚未定义--
运算符这一事实并不是什么大问题。这是一个侧面问题,您可以像++
运算符一样轻松定义它,您已编码。让我们考虑完成这部分。主要问题是您的实际end()
值:
inline iterator end() { return iterator(m_back +1); }
这在几个方面是一次重大失败。 m_back
是指向双向链表中最后一个元素的指针。 m_back
将成为最后一个元素之后的下一个内存位置。这真的不是很有意义,而且由于以下简单原因,这是完全错误的。
此外,当您的列表为空时,m_back
为空,因此m_back+1
是未定义的行为!哎呀。但是,如您所知,空容器的end()
必须是完全有效的迭代器。
现在,考虑一下iterator
引用双向链表中最后一个元素的情况。在这种情况下,使用++
运算符递增它应该为您提供end()
值。因为那就是它。现在,停下来思考一下。在operator++()
完成“递增”引用双向链表中最后一个元素的迭代器之后,会发生什么?当然不是。
此外,请记住,在新节点end()
()编辑到自定义容器末尾后,push_back
迭代器的值应保持不变的基本原则。但是当你的代码中出现这种情况时,你将会有一个全新的m_back
。 m_back+1
现在完全不同了。您之前的“m_back + 1”发生了什么变化?它突然变成了end()
值之外的其他东西。事实上,它根本没有指向双向链表的任何部分。它指向列表中某个现有元素之后的内存位置。
因此,您提到的back()
问题非常容易解决。但是,您需要解决的问题是,您需要如何设计end()
迭代器值,以及它应该是什么。你现在拥有的东西不能正常工作。