不维护迭代剂脱烯
Not maintaining iterator dereferenceability?
这是双重链接列表的迭代器的第一次尝试:
dlist.h
#ifndef dlist_h
#define dlist_h
/* Node */
template <class Elem>
struct Link
{
Link();
Link (Link<Elem>* s, Link<Elem>* p, const Elem& v);
Link (const Link<Elem>& src);
Link<Elem>& operator= (const Link<Elem>& src);
bool operator== (const Link<Elem>& src);
bool operator!= (const Link<Elem>& src);
void swap(Link<Elem>& src);
Link* succ;
Link* prev;
Elem val;
};
//----------------------------------------------------------------------------
/* Doubly Linked List */
template <class Elem>
class List
{
public:
class iterator;
List();
iterator begin() { return iterator(first, first, last); }
iterator end() { return iterator(last, first, last); }
void push_front(const Elem& v);
Elem& front();
size_t size();
void print();
private:
Link<Elem> *first;
Link<Elem> *last;
};
//----------------------------------------------------------------------------
/* a range-checked bidirectional iterator */
template <class Elem>
class List<Elem>::iterator
{
public:
iterator(); // default constructor
iterator(Link<Elem>* c, Link<Elem>* b, Link<Elem>* e);
iterator(const iterator& src); // copy constructor
iterator operator= (const iterator& src); // copy assignment
iterator& operator++(); // incrementations
iterator operator++(int); // postfix
iterator& operator--(); // decrementations
iterator operator--(int); // postfix
Elem& operator*(); // dereferenceable lvalue
const Elem& operator*() const; // dereferenceable rvalue
bool operator== (const iterator& b) const; // equality comparisons
bool operator!= (const iterator& b) const;
void swap(iterator& src);
private:
Link<Elem>* curr;
Link<Elem>* begin;
Link<Elem>* end;
};
#include "dlist.cpp"
#endif
dlist.cpp
//-----------------------------------------------------------------------------
template <class Elem>
Link<Elem>::Link()
: succ(nullptr), prev(nullptr), val(Elem())
{
}
//-----------------------------------------------------------------------------
template <class Elem>
Link<Elem>::Link (Link<Elem>* s, Link<Elem>* p, const Elem& v)
: succ(s), prev(p), val(v)
{
}
//-----------------------------------------------------------------------------
template <class Elem>
Link<Elem>::Link (const Link<Elem>& src)
: succ(src.succ), prev(src.prev), val(src.val)
{
}
//-----------------------------------------------------------------------------
template <class Elem>
Link<Elem>& Link<Elem>::operator= (const Link<Elem>& src)
{
Link<Elem> temp(src);
swap(*this, temp);
return *this;
}
//-----------------------------------------------------------------------------
template <class Elem>
bool Link<Elem>::operator== (const Link<Elem>& src)
{
return succ = src.succ && prev = src.prev;
}
//-----------------------------------------------------------------------------
template <class Elem>
bool Link<Elem>::operator!= (const Link<Elem>& src)
{
return !(*this == src);
}
//-----------------------------------------------------------------------------
template <class Elem>
void Link<Elem>::swap(Link<Elem>& src)
{
std::swap(prev, src.prev);
std::swap(succ, src.succ);
std::swap(val, src.val);
}
//-----------------------------------------------------------------------------
template<class Elem>
void swap(Link<Elem>& lhs, Link<Elem>& rhs)
{
lhs.swap(rhs);
}
//-----------------------------------------------------------------------------
template<class Elem>
List<Elem>::List()
: first(new Link<Elem>()), last(first)
{
}
//-----------------------------------------------------------------------------
template<class Elem>
void List<Elem>::push_front(const Elem& v)
{
first = new Link<Elem>(first, nullptr, v);
}
//-----------------------------------------------------------------------------
template<class Elem>
Elem& List<Elem>::front()
{
return first->val;
}
//-----------------------------------------------------------------------------
template<class Elem>
size_t List<Elem>::size()
{
size_t count = 0;
for (iterator p = begin(); p != end(); ++p)
{
++count;
}
return count;
}
//-----------------------------------------------------------------------------
template<class Elem>
void List<Elem>::print()
{
for (iterator p = begin(); p != end(); ++p)
{
std::cout << *p <<' ';
}
}
//-----------------------------------------------------------------------------
template<class Elem>
List<Elem>::iterator::iterator()
: curr(nullptr), begin(nullptr), end(nullptr)
{
}
//-----------------------------------------------------------------------------
template<class Elem>
List<Elem>::iterator::iterator(Link<Elem>* p, Link<Elem>* b, Link<Elem>* e)
: curr(p), begin(b), end(e)
{
}
//-----------------------------------------------------------------------------
template<class Elem>
List<Elem>::iterator::iterator(const iterator& src)
: curr(src.curr), begin(src.begin), end(src.end)
{
}
//-----------------------------------------------------------------------------
template<class Elem>
typename List<Elem>::iterator List<Elem>::iterator::operator= (const iterator& src)
{
iterator temp(src);
this->swap(temp);
return *this;
}
//-----------------------------------------------------------------------------
template<class Elem>
typename List<Elem>::iterator& List<Elem>::iterator::operator++()
{
if (curr == end)
{
throw std::out_of_range("List<Elem>::iterator::operator++(): out of range!n");
}
curr = curr->succ;
return *this;
}
//-----------------------------------------------------------------------------
template<class Elem>
typename List<Elem>::iterator List<Elem>::iterator::operator++(int)
{
if (curr == end)
{
throw std::out_of_range("List<Elem>::iterator::operator++(): out of range!n");
}
Link<Elem>* old = curr;
curr = curr->succ;
return old;
}
//-----------------------------------------------------------------------------
template<class Elem>
typename List<Elem>::iterator& List<Elem>::iterator::operator--()
{
if (curr == begin)
{
throw std::out_of_range("List<Elem>::iterator::operator--(): out of range!n");
}
curr = curr->prev;
return *this;
}
//-----------------------------------------------------------------------------
template<class Elem>
typename List<Elem>::iterator List<Elem>::iterator::operator--(int)
{
if (curr == begin)
{
throw std::out_of_range("List<Elem>::iterator::operator--(): out of range!n");
}
iterator old(*this);
curr = curr->prev;
return old;
}
//-----------------------------------------------------------------------------
template<class Elem>
Elem& List<Elem>::iterator::operator*()
{
return curr->val;
}
//-----------------------------------------------------------------------------
template<class Elem>
const Elem& List<Elem>::iterator::operator*() const
{
return curr->val;
}
//-----------------------------------------------------------------------------
template<class Elem>
bool List<Elem>::iterator::operator== (const iterator& b) const
{
return curr == b.curr;
}
//-----------------------------------------------------------------------------
template<class Elem>
bool List<Elem>::iterator::operator!= (const iterator& b) const
{
return curr != b.curr;
}
//-----------------------------------------------------------------------------
template<class Elem>
void List<Elem>::iterator::swap(iterator& src)
{
std::swap(curr, src.curr);
std::swap(begin, src.begin);
std::swap(end, src.end);
}
//-----------------------------------------------------------------------------
template<class Elem>
void swap(typename List<Elem>::iterator& lhs, typename List<Elem>::iterator& rhs)
{
lhs.swap(rhs);
}
main.cpp
#include <iostream>
#include "dlist.h"
/* simple test for iterator */
int main()
{
List<int> l;
l.push_front(1);
l.push_front(2);
l.push_front(3);
l.push_front(4);
l.push_front(5);
// default constructor, copy assignment
List<int>::iterator p = l.begin();
// lvalue dereferencing
*p = 100;
// incrementation, rvalue dereferencing
List<int>::iterator i;
for (i = l.begin(); i != l.end(); ++i)
{
std::cout << *i <<' ';
}
if (i == l.end() && i != l.begin())
{
std::cout <<"ncomparison correct!n";
}
// postfix and prefix decrementation; maintain dereferenceability
List<int>::iterator ii = l.end();
--ii;
for (; ii != l.begin(); ii--)
{
std::cout << *ii <<' ';
}
return 0;
}
当它到达最后一个for
循环时,减少operator--
以某种方式使ii
迭代器无效,尽管彻底 IMO 调试。
这是一个可运行的样本。
问题是您的push_front
方法,您忘了将first->succ->prev
链接回新节点,因此您的双重链接列表基本上是单个链接的列表
第一个i--
成功,因为last
指向默认节点,但是curr->prev
是一个NULLPTR,因为您忘记链接回去链接,因此下一个i--
将deref deref nullptr curr
导致错误。
修复您的push_front方法:
template<class Elem>
void List<Elem>::push_front(const Elem& v)
{
first = new Link<Elem>(first, nullptr, v);
first->succ->prev = first; //link back
}
您的Link
构造函数无法正确更新给出的参数元素。插入两个元素之间的元素打破了先前的链接。
这是一个更合适的构造函数:
template <class Elem>
Link<Elem>::Link(Link<Elem>* s, const Elem& v)
: succ(s), prev(s->prev), val(v)
{
// Update next and previous nodes to make them aware of this
s->prev = this;
if(prev) prev->succ = this;
}
如果更新List::push_front
以使用此构造函数,则会发现您的代码编译并运行。
您应该考虑在适当的情况下制作const
以避免错误(或在bool operator== (const Link<Elem>& src) const
的情况下发现现有的错误)。链接。
相关文章:
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 迭代时从向量和内存中删除对象
- 如何在c++迭代器类型中包装std::chrono
- 带过滤器的现代迭代c++集合
- 在c++中检查长方体是否尽可能快地重叠(无迭代)
- C++矢量迭代
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 擦除while循环中迭代的元素
- 实现一个在集合上迭代的模板函数
- 对于set上的循环-获取next元素迭代器
- 在向量内的向量上迭代
- 为什么output_editor Concept不需要output_e迭代器标记
- TSP递归解的迭代形式
- 树不维护递归迭代器成员
- 不维护迭代剂脱烯
- 在执行 DFS 时在 Boost::graph 中维护迭代器
- std::map::erase(it++)是否维护一个指向映射中下一个元素的有效迭代器