c++ c++迭代器实现 ++迭代器类型 - 如何实现一个STL风格的迭代器,并避免常见的陷阱?




3 Answers

http://www.cplusplus.com/reference/std/iterator/有一个方便的图表,详细介绍了C ++ 11标准的第24.2.2节的规范。 基本上,迭代器具有描述有效操作的标签,并且标签具有层次结构。 下面是纯粹的符号,这些类实际上并不存在。

iterator {
    iterator(const iterator&);
    ~iterator();
    iterator& operator=(const iterator&);
    iterator& operator++(); //prefix increment
    reference operator*() const;
    friend void swap(iterator& lhs, iterator& rhs); //C++11 I think
};

input_iterator : public virtual iterator {
    iterator operator++(int); //postfix increment
    value_type operator*() const;
    pointer operator->() const;
    friend bool operator==(const iterator&, const iterator&);
    friend bool operator!=(const iterator&, const iterator&); 
};
//once an input iterator has been dereferenced, it is 
//undefined to dereference one before that.

output_iterator : public virtual iterator {
    reference operator*() const;
    iterator operator++(int); //postfix increment
};
//dereferences may only be on the left side of an assignment
//once an output iterator has been dereferenced, it is 
//undefined to dereference one before that.

forward_iterator : input_iterator, output_iterator {
    forward_iterator();
};
//multiple passes allowed

bidirectional_iterator : forward_iterator {
    iterator& operator--(); //prefix decrement
    iterator operator--(int); //postfix decrement
};

random_access_iterator : bidirectional_iterator {
    friend bool operator<(const iterator&, const iterator&);
    friend bool operator>(const iterator&, const iterator&);
    friend bool operator<=(const iterator&, const iterator&);
    friend bool operator>=(const iterator&, const iterator&);

    iterator& operator+=(size_type);
    friend iterator operator+(const iterator&, size_type);
    friend iterator operator+(size_type, const iterator&);
    iterator& operator-=(size_type);  
    friend iterator operator-(const iterator&, size_type);
    friend difference_type operator-(iterator, iterator);

    reference operator[](size_type) const;
};

您可以专门化std::iterator_traits<youriterator> ,或者将相同的std::iterator_traits<youriterator>放入迭代器本身,或者从std::iterator (它有这些typedef)继承。 我更喜欢第二种选择,以避免更改std名称空间中的内容,并且为了便于阅读,但大多数人从std::iterator继承。

struct std::iterator_traits<youriterator> {        
    typedef ???? difference_type; //almost always ptrdiff_t
    typedef ???? value_type; //almost always T
    typedef ???? reference; //almost always T& or const T&
    typedef ???? pointer; //almost always T* or const T*
    typedef ???? iterator_category;  //usually std::forward_iterator_tag or similar
};

请注意,iterator_category应该是std::input_iterator_tagstd::output_iterator_tagstd::forward_iterator_tagstd::random_access_iterator_tagstd::random_access_iterator_tag ,具体取决于迭代器满足哪些要求。 根据您的迭代器,您可以选择专门化std::nextstd::prevstd::advancestd::distance ,但这很少需要。 在极少数情况下,您可能希望专门化std::beginstd::end

你的容器应该也可能有一个const_iterator ,它是一个(可能是可变的)迭代器,用于处理类似于迭代器的常量数据,除非它应该可以从iterator隐式构造,并且用户应该无法修改数据。 它的内部指针是一个指向非常量数据的指针,并且具有从const_iterator继承的iterator以最小化代码重复。

我在写你自己的STL容器的文章有一个更完整的容器/迭代器原型。

迭代器比较 c++迭代器指针

我做了一个集合,我想提供一个STL风格的随机访问迭代器。 我正在寻找一个迭代器的示例实现,但我没有找到任何。 我知道[]*运算符需要const重载。 迭代器对“STL风格”有什么要求,还有哪些其他陷阱可以避免(如果有的话)?

额外的上下文:这是一个图书馆,我不想介绍任何依赖它,除非我真的需要。 我编写自己的集合,以便能够使用相同的编译器提供C ++ 03和C ++ 11之间的二进制兼容性(因此没有STL可能会中断)。







首先,您可以http://www.cplusplus.com/reference/std/iterator/查看各个迭代器类型需要支持的各种操作的列表。

接下来,当您创建了迭代器类时,您需要为它专门化std::iterator_traits并提供一些必要的typedefs(如迭代器类别或值类型),或者从std::iterator派生它,这会为您定义所需的typedefs因此可以使用默认的std::iterator_traits

免责声明:我知道有些人不太喜欢cplusplus.com ,但他们提供了一些非常有用的信息。




Related