2017-02-21 57 views
0

這是在實現一個迭代器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

代替上述期望輸出的獲取:

調試斷言失敗
表達:列表迭代器不dereferencable。

爲什麼我得到這種行爲以及如何糾正?


注:短暫的研究之後,我發現,最常見的原因爲這樣的行爲是在提領該end()迭代器的嘗試,但我無法找到我的代碼這樣的表達。

+1

您的迭代器需要存儲每個容器的結尾以及開始。 –

回答

1

您正在取消引用Document::end()中的結束迭代器*text.end()。最容易解決的問題是使用list::back()(和list::front()Document::begin())。

修復該問題後,您會發現Text_iterator::operator++也會取消引用結束迭代器,因爲您沒有在適當的末尾檢查ln。 @Jonathan波特的評論是正確的,你需要傳遞text.end()Text_iterator小號

變化:

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()); 
} 

當最後的增量出現,正將指向最終Line結束迭代器,和ln將指向文本的結束迭代器,這是我們傳遞給構造函數的Document::end()。我們不需要比較或暴露Text_iterator::ln_end保留明智的語義。