这是第一次尝试实现std::list<std::vector<char>>
的迭代器:
Document.h
#ifndef Document_h
#define Document_h
//-------------------------------------------------------------------------
typedef std::vector<char> Line; // line of text
//-------------------------------------------------------------------------
class Text_iterator
{
public:
Text_iterator(std::list<Line>::iterator l, Line::iterator p)// constructor
: ln(l), pos(p) { }
Text_iterator(const Text_iterator& src) // copy constructor
: ln(src.ln), pos(src.pos) { }
Text_iterator& operator= (const Text_iterator& src) // copy assignment
{
Text_iterator temp(src);
this->swap(temp);
return *this;
}
char& operator*() { return *pos; } // dereferencing
Text_iterator& operator++ () // incrementation
{
++pos;
if (pos == ln->end())
{
++ln;
pos = ln->begin();
}
return *this;
}
bool operator== (const Text_iterator& other) const // comparison
{
return ln == other.ln && pos == other.pos;
}
bool operator != (const Text_iterator& other) const // comparison
{
return !(*this == other);
}
void swap(Text_iterator& src) // helper: swap
{
std::swap(src.get_line(), ln);
std::swap(src.get_column(), pos);
}
std::list<Line>::iterator get_line() { return ln; } // accessors
Line::iterator get_column() { return pos; }
private:
std::list<Line>::iterator ln; // data members
Line::iterator pos;
};
//-------------------------------------------------------------------------
void swap (Text_iterator& lhs, Text_iterator& rhs) // object swap
{
lhs.swap(rhs);
}
//-------------------------------------------------------------------------
class Document
{
public:
typedef Text_iterator iterator;
public:
Document() // constructor
{
Line l(10, 'a');
text.push_back(l);
}
iterator begin() // iterator to first element
{
return iterator(text.begin(), (*text.begin()).begin());
}
iterator end() // iterator to last element
{
return iterator(text.end(), (*text.end()).end());
}
void print()
{
for (Document::iterator p = begin(); p != end(); ++p)
{
std::cout << *p;
getchar();
}
}
std::list<Line> text; // data member
};
#endif
main.cpp
#include <iostream>
#include <sstream>
#include <vector>
#include <list>
#include <algorithm>
#include "Document.h"
int main()
{
Document text;
text.print();
}
预期产出:
AAAAAAAAAA
而不是我得到的上述预期输出:
Debug Assertion Failure
Expression:list iterator not dereferencable。
为什么我会遇到这种行为以及如何纠正它?
注意:经过简短的研究后,我发现导致这种行为的最常见原因是尝试取消引用end()
迭代器,但我在代码中找不到这样的表达式。
答案 0 :(得分:1)
您正在取消引用*text.end()
中的结束迭代器Document::end()
。最容易解决的问题是使用list::back()
(以及list::front()
中的Document::begin()
)。
修复后,您会发现Text_iterator::operator++
也会取消引用结束迭代器,因为您没有在适当的末尾检查ln
。 @Jonathan Potter的评论是对的,您需要将text.end()
传递给Text_iterator
s
的变化:
class Text_iterator
{
// Declarations elided
private:
std::list<Line>::iterator ln;
std::list<Line>::iterator ln_end;
Line::iterator pos;
}
Text_iterator::Text_iterator(std::list<Line>::iterator l, std::list<Line>::iterator l_end, Line::iterator p)
: ln(l), ln_end(l_end), pos(p) { }
Text_iterator::Text_iterator(const Text_iterator& src)
: ln(src.ln), ln_end(src.ln_end), pos(src.pos) { }
Text_iterator& Text_iterator::operator++ ()
{
++pos;
if (pos == ln->end())
{
++ln;
if(ln != ln_end)
{
pos = ln->begin();
}
}
return *this;
}
void Text_iterator::swap(Text_iterator& src)
{
std::swap(src.ln, ln);
std::swap(src.ln_end, ln_end);
std::swap(src.pos, pos);
}
Document::iterator Document::begin()
{
return iterator(text.begin(), text.end(), text.front().begin());
}
Document::iterator Document::end()
{
return iterator(text.end(), text.end(), text.back().end());
}
当最终增量发生时,pos将指向最终Line
的结束迭代器,并且ln将指向文本的结束迭代器,这是我们传递给Text_iterator
构造函数的{ {1}}。我们不需要比较或公开Document::end()
来保留合理的语义。