C++11 为自定义容器实现标准的forward迭代器

原创 2015年11月21日 18:29:32

当前我的一个项目是基于C++11为基础开发的,在项目中需要用到哈希表来保持数据,C++11本身已经提供了丰富的容器类型(array,list,hashmap….vector),但因为项目的特殊需要不能使用C++11现成的unordered_map容器。无奈所以我只能自己根据项目需要写了一个哈希表的模板类–HashTableAbstract–也就是自定义容器。
然后问题了,为了让这个自定义的容器也能像unordered_map一样使用forward(向前)迭代器进行遍历数据,还要为它实现一个forward迭代器。下面以此为例来简要说明为自定义的容器实现标准的迭代器的办法。

HashTableAbstract的部分相关代码

/* 实现哈希表的抽象类,
 */
template<typename K, typename V>
class HashTableAbstract {
public:
    using  iterator=_HashTable_Iterator<V>;//定义迭代器类型
    iterator begin ()noexcept
    { return iterator(this->m_table); }//返回指向hashtable起始位置的迭代器
    iterator end()noexcept
    { return iterator(this->m_table,this->m_table.capacity); }//返回指向hashtable结尾位置的迭代器
}

下面是为HashTableAbstract定制的forward(向前)迭代器的主要的代码实现:

#include <cassert>
#include <type_traits>
#include <iterator>
/* 实现hashtable 标准的forward迭代器
 */
template<typename V>
// 继承自`std::iterator` V指哈希表中元素类型 
// std::forward_iterator_tag用于定义迭代器类型,这里是指forward迭代器
struct _HashTable_Iterator:public std::iterator<std::forward_iterator_tag,V>{
    typedef _HashTable_Iterator<V>      _Self;
    typedef _HashNode                   _Node;
    typedef V&                          reference;
    typedef V*                          pointer;
    const HashtableCore &m_table;
    HASH_TABLE_SIZE_TYPE m_index;
    HASH_NODE_PTR m_pNode;
    // 构造函数
    explicit
    _HashTable_Iterator(HashtableCore &table,decltype(m_index) index=0)noexcept:m_table(table),m_index(index){
//do somthing
    }
    /*_HashTable_Iterator(const _HashTable_Iterator &)=default;
    _Self& operator=(const _HashTable_Iterator &)=default;*/
    // 实现 前置自增操作符++
    _Self& operator++()noexcept{
    //do something
        return *this;
    }
    // 实现 后置自增操作符++
    _Self operator++(int){
        _Self tmp=*this;
        ++(*this);
        return tmp;
    }
    // 实现 取容器元素内容操作符*
    reference operator*() const noexcept
    { return *static_cast<V*>(m_pNode->obj);}
    // 实现 取对象地址操作符-> (访问容器元素的成员)
    pointer operator->() const noexcept
    { return static_cast<V*>(m_pNode->obj);}
    // 实现比较操作符(相等)==
    bool
    operator==(const _Self& v) const noexcept
    { return &m_table==&v.m_table&&m_index == v.m_index&&m_pNode==v.m_pNode; }
    // 实现比较操作符(不相等)!=
    bool
    operator!=(const _Self& v) const noexcept
    { return &m_table!=&v.m_table||m_index != v.m_index||m_pNode!=v.m_pNode; }
};

这样,HashTableAbstract就拥有了一个标准的向前(forward)迭代器,于是我们可以像使用其他标准容器一样用迭代器遍历整张哈希表:

HashTableAbstract <int,int> hashtab;
        for(auto itor=hashtab.begin();itor!=hashtab.end();itor++)
            top.insert((*itor), FCUtils::compare(node->code, code));

还可以利用C++11的新特性:基于范围的for循环( the range-base for statement)将代码更加简化:

HashTableAbstract <int,int> hashtab;
        for(const auto &node:hashtab)
            top.insert(node, FCUtils::compare(node.code, code));

总结

实现自定义的迭代器并不复杂,主要注意几点:

  • 自定义迭代器必须继承自std::iterator,
    其实std::iterator只是个元模板,里面没什么内容,主要是定义了迭代器特性(std::iterator_traits),为你的自定义迭代器定义了标准迭代器所需要的的5种数据类型,这里涉及到C++的元模板编程,不在本话题的范围,就不深入说了,有兴趣可以找找关于这方面的资料来看。
  template<typename _Tp>
    struct iterator_traits<_Tp*>
    {
      //迭代器类型 (分为output,input,forward,bidirectional,radom_access五种)
      typedef random_access_iterator_tag iterator_category;
      typedef _Tp                         value_type;//容器中元素的类型
      typedef ptrdiff_t                   difference_type;//步长类型(用于计算元素之间的距离)
      typedef _Tp*                        pointer;//容器中元素指针类型
      typedef _Tp&                        reference;//容器中元素引用类型
    };
  • 必须实现指定类型的迭代器所必须的操作(符)

以本例中的forward迭代器为例,按照《C++标准库(第2版)》的说明需要实现以下操作符:

表达式 效果 说明
*iter 访问实际元素
iter-> 访问实际元素的成员
++iter 向前步进(返回新位置)
++iter 向前步进(返回旧位置)
iter1==iter2 判断两个迭代器是否相等
iter1!=iter2 判断两个迭代器是否不相等
TYPE() 创建迭代器(default 构造函数) *
TYPE(iter) 复制迭代器(copy 构造函数) *
iter1=iter2 对迭代器赋值(assign) *

但在上面的代码中实现中表中打*号的操作都没有实现,代码也能正常编译,具体为什么有时间再研究。

版权声明:本文为博主原创文章,转载请注明源地址。

Java 实现迭代器(Iterator)模式

类图 /** * 自定义集合接口, 类似java.util.Collection * 用于数据存储 * @author stone * */ public interface IColl...
  • jjwwmlp456
  • jjwwmlp456
  • 2014年10月11日 12:21
  • 4577

使用reverse_iterator迭代器实现STL容器的反向遍历

某些时候因为一些特殊的
  • chenlycly
  • chenlycly
  • 2014年11月05日 21:57
  • 1485

C++11—迭代器类实现

//迭代器类 namespace detail_range { template class iterator { public: using value_type = T; usi...
  • J_Anson
  • J_Anson
  • 2017年04月24日 16:25
  • 453

自定义双向列表容器(含迭代器)

实现双向列表迭代器的实现是重载一些常用的操作符来对node进行一个封装。 实际的数据是存储在node的链表里面。...
  • jiayichendddd
  • jiayichendddd
  • 2013年04月16日 04:15
  • 845

Chapter 11.顺序容器forward_list[c++11]

前向链表简介 前向链表是用单链表实现的,可在常量时间内在链表中做插入或删除操作 list比之forward_list,双向链表要消耗额外的空间存储每个元素和在插入和删除元素时一个轻微的更高...
  • vv_VV_vv
  • vv_VV_vv
  • 2012年09月18日 00:09
  • 5254

C++11 你真的会用迭代器(iterator)么?

C++ STL提供了丰富的标准容器(Container)对象(vector,array,queue,list,set,unordered_map/set…),让我们可以根据需求选择不同的容器管理各种类...
  • 10km
  • 10km
  • 2015年11月22日 09:35
  • 2163

【C++ STL应用与实现】7: 如何使用std::forward_list 单链表 (since C++11)

本文介绍了STL中的序列式容器`std::forward_list`, 从它的名字就能推测出来,它是单向的,只能前进(forward). 确实如此,它其实就是对C语言风格的单链表的封装,仅提供有限的接...
  • elloop
  • elloop
  • 2015年12月25日 23:46
  • 3487

C++ vector容器(包含c++11标准)

构造函数 语法:    vector();   vector( size_type num, const TYPE &val );   vector( const vector &from )...
  • qq_36196684
  • qq_36196684
  • 2016年11月21日 09:36
  • 128

计算部分的数量树- 了解树的表示方法Map容器- 了解如何日用标准库中的map容器以及迭代器递归- 了解如何构造一个递归的解决方案去解决一个问题

  • 2014年04月22日 20:13
  • 1KB
  • 下载

C++标准库---容器、迭代器、算法、仿函数

容器:用来管理某类对象的集合,不同容器有不同的优缺点,所以正确使用不同的容器,可以获得容器带来的各种好处,但是如果使用不正确,就势必会造成很多麻烦,甚至造成错误。 迭代器:用来对一个对象群集...
  • lanzhihui_10086
  • lanzhihui_10086
  • 2014年11月29日 15:05
  • 965
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++11 为自定义容器实现标准的forward迭代器
举报原因:
原因补充:

(最多只允许输入30个字)