C++中的自定义迭代器

Sug*_*gar 29 c++ iterator stl

我有一个类TContainer,它是指向TItems类的几个stl集合指针的集合.

我需要创建一个迭代器来遍历我的TContainer类中所有集合中的元素,从而抽象出内部工作的客户端.

这样做有什么好办法?我应该创建一个扩展迭代器的类(如果是这样,我应该扩展什么迭代器类),我应该创建一个迭代器类,它是迭代器的集合吗?

我只需要一个FORWARD_ONLY迭代器.

IE,如果这是我的容器:

typedef std::vector <TItem*> ItemVector;
class TContainer {
   std::vector <ItemVector *> m_Items;
};
Run Code Online (Sandbox Code Playgroud)

遍历m_Items成员变量向量中包含的所有项的好迭代器是什么.

Mar*_*ork 31

当我做自己的迭代器(前一段时间)时,我继承自std :: iterator并将该类型指定为第一个模板参数.希望有所帮助.

对于前向迭代器,请使用以下代码中的forward_iterator_tag而不是input_iterator_tag.

这个类最初来自istream_iterator类(并且我自己修改了它,因此它可能不再像istram_iterator那样).

template<typename T>
class <PLOP>_iterator
         :public std::iterator<std::input_iterator_tag,       // type of iterator
                               T,ptrdiff_t,const T*,const T&> // Info about iterator
{
    public:
        const T& operator*() const;
        const T* operator->() const;
        <PLOP>__iterator& operator++();
        <PLOP>__iterator operator++(int);
        bool equal(<PLOP>__iterator const& rhs) const;
};

template<typename T>
inline bool operator==(<PLOP>__iterator<T> const& lhs,<PLOP>__iterator<T> const& rhs)
{
    return lhs.equal(rhs);
}
Run Code Online (Sandbox Code Playgroud)

请查看有关迭代器标记的文档:http:
//www.sgi.com/tech/stl/iterator_tags.html

刚刚重新阅读有关迭代器的信息:http:
//www.sgi.com/tech/stl/iterator_traits.html

这是旧的处理方式(iterator_tags),更现代的方法是为迭代器设置iterator_traits <>,使其与STL完全兼容.

  • `std :: iterator`具有引用和指针类型的默认参数,因此您不必在示例中键入它们.让你的类继承自`std :: iterator`会自动为你专门化`iterator_traits`,所以它是编写迭代器的现代方法. (9认同)
  • 与继承自std :: iterator相比,您自己的iterator_traits特化与STL的兼容性如何? (3认同)

Jam*_*kin 22

如果您可以访问Boost,使用iterator_facade是最强大的解决方案,并且使用起来非常简单.


Man*_*uel 18

首先让我们概括一下:

typedef int value_type;
typedef std::vector<value_type*> inner_range;
typedef std::vector<inner_range*> outer_range;
Run Code Online (Sandbox Code Playgroud)

现在迭代器:

struct my_iterator : std::iterator_traits<inner_range::iterator> 
{
    typedef std::forward_iterator_tag iterator_category;

    my_iterator(outer_range::iterator const & outer_iterator, 
                outer_range::iterator const & outer_end)
    : outer_iterator(outer_iterator), outer_end(outer_end)
    { 
        update();
    }

    my_iterator & operator++()
    {
        ++inner_iterator;
        if(inner_iterator == inner_end)
        {
            ++outer_iterator;
            update();
        }
        return *this;
    }

    reference operator*() const
    {   
        return *inner_iterator;
    }

    bool operator==(my_iterator const & rhs) const
    {   
        bool lhs_end = outer_iterator == outer_end;
        bool rhs_end = rhs.outer_iterator == rhs.outer_end;
        if(lhs_end && rhs_end)
            return true;
        if(lhs_end != rhs_end)
            return false;
        return outer_iterator == rhs.outer_iterator 
            && inner_iterator == rhs.inner_iterator;
    }

private:

    outer_range::iterator outer_iterator, outer_end;
    inner_range::iterator inner_iterator, inner_end;

    void update()
    {
        while(outer_iterator != outer_end)
        {
            inner_iterator = (*outer_iterator)->begin();
            inner_end = (*outer_iterator)->end();
            if(inner_iterator == inner_end)
                ++outer_iterator;
            else
                break;
        }
    }    
};
Run Code Online (Sandbox Code Playgroud)

此类假定外部迭代器包含指向内部范围的指针,这是您的问题中的要求.这反映在update成员中,在箭头之前begin()和之前end().如果要在外部迭代器按值包含内部范围的更常见情况下使用此类,则可以用点替换这些箭头.注意BTW,这个类与内部范围包含指针的事实无关,只有类的客户端才需要知道.

如果我们使用代码可能会更短,boost::iterator_facade但没有必要为这么简单的事情添加一个boost依赖.此外,唯一棘手的部分是相等和增量操作,无论如何我们必须对它们进行编码.

我把以下的锅炉板成员留给了"为读者练习":

  • 后缀增量迭代器
  • 运算符!=
  • 默认构造函数
  • 操作符 - >

另一个有趣的练习是将其转换为适用于任意容器的模板.代码基本相同,只是你必须typename在几个地方添加注释.

使用示例:

int main()
{
    outer_type outer;
    int a = 0, b = 1, c = 2;
    inner_type inner1, inner2;
    inner1.push_back(&a);
    inner1.push_back(&b);
    inner2.push_back(&c);
    outer.push_back(&inner1);
    outer.push_back(&inner2);

    my_iterator it(outer.begin(), outer.end());
                e(outer.end(), outer.end());
    for(; it != e; ++it)
        std::cout << **it << "\n";
}
Run Code Online (Sandbox Code Playgroud)

哪个印刷品:

0 1 2


小智 7

迭代器只是一个支持某个接口的类.至少,您希望能够:

  • 增加和/或减少它
  • 取消引用它以获得它"指向"的对象
  • 测试它是否存在平等和不平等
  • 复制并分配它

一旦你有一个可以为你的集合明智地做这个的类,你将需要修改集合以具有返回迭代器的函数.至少你会想要的

  • 一个begin()函数,它返回位于第一个元素的新迭代器类型的实例
  • 一个end()函数,它返回一个迭代器,该迭代器(可能是名义上的)位于容器中项目末尾的一个位置