寻找一种在std :: map上自定义迭代器的方法

时间:2012-04-19 08:08:30

标签: c++ iterator

我在代码中使用std :: map来存储数据。使用map的迭代器访问和/或修改元素非常容易,但是因为我真的需要抑制一些操作(比如++,[]等),我不知道它是否属实,但似乎很少文章建议不要直接继承std :: map,所以我正在编写一个包装器。

class MyContainer
{
  private:
    std::map<int, int> data;

  public:
    int &operator[](int); // here we write the interface to control the behavior of accessing the data element
    void &operator++();
    void &operator--();
};

但这导致了另一个问题。实际上,我在代码中的每个地方使用迭代器来访问/修改元素。但是在地图移动到自定义类之后,我不能再使用主程序中的迭代器来处理数据了。有人建议编写我自己的迭代器,但在阅读了几篇文章之后,似乎人们建议通过继承std :: iterator来自定义我们自己的迭代器。这似乎很简单但对我来说仍然太抽象。我有两个疑惑

1)我将迭代map,但我的包装器实际上不是一个容器。并且为了控制地图元素上的以下操作(++, - ,[])的行为,我应该让自定义迭代器引用MyContainer而不是map。这似乎让我感到困惑,因为我们需要提前映射,但迭代器会引用包装器。我不知道如何使它工作,有什么例子我可以遵循类似的情况?感谢。

2)我不希望代码直接访问map元素,因此,我已经在包装器中定义了运算符

int &operator[](int)

在上面的函数中,返回的引用取决于输入参数,也就是说,对于某些情况,它可以返回NULL引用而不是引用元素。但是如果返回NULL,则以下调用不再有效

data[3]++;

因为data [3]可以返回空引用。但是如何在更新元素之前检查返回的引用是否为null?

2 个答案:

答案 0 :(得分:2)

我认为为元素'++运算符等实现特殊行为是过度的。同样,对于迭代器的递增和递减操作。我认为一个好的解决方案就是将绑定检查添加到[]访问器中,并在必要时抛出一个超出范围的异常。因此,请使用地图的begin()end()方法,并将绑定检查添加到[]

class MyContainer
{
  private:
    std::map<int, int> data;
  public:
    typedef std::map<int, int> MapType;
    typedef MapType::iterator iterator;
    typedef MapType::const_iterator const_iterator;
    typedef MapType::reference reference;
  public:
    iterator begin() {return data.begin();}
    const_iterator begin() const { return data.begin();}
    // and so on ...
    reference operator[](size_t i) {
      if (data.size()<=i) { /* raise exception here */ }
      return data[i];
    }
    const reference operator[](int) const { /* same as above */}

};

这样做的好处是返回类型与标准库容器的类型相匹配。

答案 1 :(得分:0)

如果您需要迭代它,可以让您“公开”公开。 否则,不要提供迭代接口,在里面做所有事情(需要迭代)。