迭代器类指南

Posted

技术标签:

【中文标题】迭代器类指南【英文标题】:Guidelines to an Iterator Class 【发布时间】:2011-02-27 03:47:37 【问题描述】:

我有一个用 c++ 实现的红色黑色树。它支持 STL 映射的功能。树节点包含键和映射的值。我想为此编写一个迭代器类,但我不知道该怎么做。我应该让它成为 Tree 类的内部类吗?谁能给我一些关于如何编写它的指南+一些资源??

谢谢!!

【问题讨论】:

供您参考,大多数 STL 实现都将其 std::map 基于红黑树,因此除非出于教育目的,否则您可以考虑使用 std::map 而不是自己制作。 【参考方案1】:

当然,阅读这篇关于编写 STL 迭代器的好文章,它可能会给你所需的概述:

http://www.drdobbs.com/184401417

一般来说,是的,内部类是好的,因为迭代器需要访问您的实现特定的树节点:

struct container  ...
public:
  struct iterator 
    // these typedefs are needed if you want to be STL compatible
    typedef std::forward_iterator_tag iterator_category;
    typedef T         value_type;
    typedef T*        pointer;
    typedef T&        reference;
    typedef size_t    size_type;
    typedef ptrdiff_t difference_type;

    // the element points to your implementation node
    iterator( element* init = 0 ) : current(init) 
    T& operator*()  return current->data;  // dereference
    const T& operator*() const  return current->data; 
    iterator& operator++()  // prefix
      if ( current ) current = current->next;
      return *this;
    
    iterator operator++(int)  // postfix
      iterator temp = *this;
      ++*this;
      return temp;
    
    bool operator==(const iterator& x) const  return current == x.current; 
    bool operator!=(const iterator& x) const  return current != x.current; 

  private:
    // the element points to your implementation node
    element* current;
  
  ...

这里的好处是,虽然迭代器是公共的,但元素仍然可以保持私有 :)。是的,上面的代码也是 STL 兼容的!

【讨论】:

非常感谢 Kornel。这正是我想要的,它非常有用:D @Kornel:还有一个问题,能否请您在第二条评论之后解释一下代码行,iterator( element* init = 0 ) : current(init) 我无法理解冒号后面的部分。谢谢! @isurulucky,这是一个初始化列表(codeguru.com/forum/showthread.php?t=464084) iterator( element* init = 0 ) current = init;基本相同 @isurulucky,没问题——如果您对它满意,请接受答案:)【参考方案2】:

我想我会添加自己的一小部分建议。

首先我要指出的是iteratorconst_iterator 很可能有很多共同点。然而,尽管它们的代码相似,但并不完全相同。这需要模板。

我要注意的第二件事是 const_iterator 应该可以从 iterator 构造(隐式),但不能反过来。

我要注意的第三件事是,如果您希望拥有类似map 的界面,那么您还需要提供reverse_iteratorconst_reverse_iterator

从风格的角度来看,我倾向于不将iterator 本身的实现放在类中。当类实现中包含太多代码以至于您难以查看可用的类型和方法时,我发现它不可读。出于这个原因,我建议将实现放在类之外。

最后,我绝对推荐 Boost.Iterator。您可能不会使用它,但请阅读材料,它会让您深入了解如何编写一次代码并将其用于 4 种!

快速说明:

namespace detail 
  template <class Value> class base_iterator;


template <class Value>
class container

public:
  typedef detail::base_iterator<Value> iterator;
  typedef detail::base_iterator<Value const> const_iterator;

  typedef boost::reverse_iterator<iterator> reverse_iterator;
  typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
;

我不了解你,但是当我只完成四分之一的工作并利用编译​​器/库为我完成其余工作时,我感觉很好 :)

【讨论】:

【参考方案3】:

迭代器类需要是一个嵌套类,或者至少是一个 typedef,它将 your_map::iterator 别名为在别处定义的某种类型。不过,嵌套类通常是最干净/最简单的路线。

就资源而言,一个可能的帮助来源是Boost::iterator 库,其中包含旨在使迭代器更易于实现的组件。

【讨论】:

+1 for boost::iterator -- 但是如果有人使用他自己的红黑树而不是使用 STL,那么他可能无论如何都不会使用 Boost。 @Kornel:这可能是——我不得不承认我写的所有迭代器都是“从头开始”的,标准是我的主要资源......

以上是关于迭代器类指南的主要内容,如果未能解决你的问题,请参考以下文章

自定义迭代器类与生成器?

迭代器模式

31 迭代器 Iterator 是什么?

STL详解—— list的模拟实现

迭代器模式

顶端迭代器