重载Iterator:C ++语义问题

时间:2011-08-20 05:08:43

标签: c++ stl iterator

请注意,此代码不是我写的。否则我不会问这个问题。完全归功于Jerry Coffin。无论如何,代码通过重载std :: iterator<生成一系列数字。 >

我将首先发布代码,然后我会解释我所看到的内容。如果一个专家C ++成员可以纠正我,如果我错了,我会非常感激。

代码

static const int N = 10;
template <class T>
class sequence : public std::iterator<std::forward_iterator_tag, T>
{
private:
    T val;
public:
    sequence(T init) : val(init) { }
    T operator *( ) { return val; }
    sequence &operator++( ) { ++val; return *this; }
    bool operator != ( const sequence &other ) { return val != other.val; }
};

void foo( )
{
    typedef std::vector<int> graph;
    graph id1( gen_seq(0), gen_seq( N ) );
    display( id1 );                             /* Not declared */
}

/* displays: 0 1 2 3 4 5 6 7 8 9 */

所以当看到这个时,我看到你创建了一个包含值的类。现在我们将其中两个传递给vector的构造函数,它可以使用两个迭代器。现在每次向量的构造函数在“序列”上使用++运算符时,它会递增迭代器内部的值。从技术上讲,你可以写:

graph id1( gen_seq( 0 ), gen_seq( 0 ) );

这会生成相同的序列吗?或者是!=运算符检查以确保0没有进入N.任何输入都会有很大帮助。我刚刚阅读了Stroustrup的C ++编程语言第3版,在那里他谈到了迭代器,但是继承它们并不是一个很大的话题,而我还没有完全理解。好吧,我会做他所有的练习,因为我记得他要求多次重载迭代器。

2 个答案:

答案 0 :(得分:5)

你真的没有重载迭代器;你正在编写自己的迭代器,这涉及到一些运算符的重载。

std::vector构造函数实际上看起来像这样:

template <typename ForwardIterator>
vector(ForwardIterator first, ForwardIterator last)
{
    for (ForwardIterator it = first; it != last; ++it)
        push_back(*it);
}

(实际上,它比这更复杂,因为它需要更有效地处理随机可访问范围,但对于前向可迭代范围,这就是它的作用。)

如您所见,该构造函数对您的迭代器执行三个操作:它取消引用它(*it),它递增它(++it),并执行不等式比较({{1} })。它执行上述每个操作的位置,它会调用您在自定义迭代器类中定义的相应运算符。

it != last会起作用,但不会产生相同的结果:它会使graph id1( gen_seq( 0 ), gen_seq( 0 ) );为空。根据前几段的解释,你明白为什么吗?

答案 1 :(得分:3)

graph id1( gen_seq( 0 ), gen_seq( 0 ) );将生成零大小的矢量。使用!=的第二个解释更接近。如果你理解了矢量ctor代码,可能会有所帮助。它是这样的

template <class II>
vector::vector(II first, II last)
{
  while (first != last)
  {
    push_back(*first);
    ++first;
  }
}

如您所见,!=用于确定何时停止向向量添加项目。

(由于各种技术和效率原因,实际的矢量ctor代码可能比这复杂得多,但上面给出了适用于你的情况的本质)。