STL: reverse_iterator / iterator 关系以及 erase 相关(C++)

原创 2015年11月17日 17:31:38

    反向迭代器

    相信大家对正向迭代器应该都很熟悉,然而对于反向迭代器的使用确是有几处需要注意的地方,在此记录一下。先看STL源码处注释如下:

  /**
   *  Bidirectional and random access iterators have corresponding reverse
   *  %iterator adaptors that iterate through the data structure in the
   *  opposite direction.  They have the same signatures as the corresponding
   *  iterators.  The fundamental relation between a reverse %iterator and its
   *  corresponding %iterator @c i is established by the identity:
   *  @code
   *      &*(reverse_iterator(i)) == &*(i - 1)
   *  @endcode
   *
   *  <em>This mapping is dictated by the fact that while there is always a
   *  pointer past the end of an array, there might not be a valid pointer
   *  before the beginning of an array.</em> [24.4.1]/1,2
   *
   *  Reverse iterators can be tricky and surprising at first.  Their
   *  semantics make sense, however, and the trickiness is a side effect of
   *  the requirement that the iterators must be safe.
  */

也即两者相差一个元素,从一个反向迭代器获得对应的正向迭代器需要使用 base() 方法,如下图应该可以清楚阐明两者的关系

                                                 

即:如果 ri 为指向元素 3 的反向迭代器,则调用 base() 方法 i = ri.base() 得到的将是指向元素 4 的正向迭代器 i 。

    vector<int> vec = {1, 2, 3, 4, 5, 6};

    vector<int>::reverse_iterator rfirst = reverse_iterator<vector<int>::iterator>(vec.end());
    vector<int>::reverse_iterator rlast = reverse_iterator<vector<int>::iterator>(vec.begin());
    vector<int>::reverse_iterator rsecond = next(rfirst);

    cout << *rfirst << endl;
    cout << *rsecond << endl;
    cout << *(rsecond.base()) << endl;

得到的输出如下

6
5
6

    反向迭代器删除元素

    所有的 erase 函数都只接受正向迭代器 iterator,所以如果想在反向遍历删除元素时必须要将 reverse_iterator 转换为 iterator 后再执行 erase 操作,所以反向迭代器与正向迭代器相差 1 的这个细节在这里必须要考虑清楚。比如按上图 ri 指向元素 3,但转换为正向迭代器后实际为指向元素 4 的位置,为了能正确执行删除,必须先将反向迭代器前进 1 步再转为正向迭代器。

    vector<int> vec = {1, 2, 3, 4, 5, 6};

    for(auto rit = vec.rbegin(); rit != vec.rend();){
        if(*rit % 2 == 0){
            vec.erase((++rit).base());
        }else{
            ++rit;
        }
    }

    for(auto& x : vec)
        cout << x << " ";

输出结果为

1 3 5

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【C++ STL学习之八】逆向迭代器reverse_iterator

对于逆向迭代器,很重要的一点是需要弄清楚逻辑位置和实际位置二者的区别。 下图显示了逆向迭代器的位置和所指的数值: 可以发现,逆向迭代器所指位置(实际位置)和所代表的的数值(逻辑...

STL 使用 erase 删除元素时 iterator 失效

STL中的容器按存储方式分为两类:一类是序列容器(如:vector,deque),另一类是关联容器(如:list,map,set)。 在使用erase方法删除元素时,有几点需要注意: 1) 对于...

从零开始学C++之STL(三):迭代器类vector::iterator 和 vector::reverse_iterator 的实现、迭代器类型、常用的容器成员

一、迭代器 迭代器是泛型指针 普通指针可以指向内存中的一个地址 迭代器可以指向容器中的一个位置 STL的每一个容器类模版中,都定义了一组对应的迭代器类。使用迭代器,算法函数可以访问容器中指定位置...

stl 学习笔记14 Reverse Iterator

//逆向迭代器,跟正向的迭代器一样是半开区间,但以相反的方向。 // //iter/reviter1.cpp //-rbegin - //-rend- #include #include #...

STL 逆向迭代器 reverse_iterator 的逻辑位置与实际位置

对于逆向迭代器,很重要的一点是需要弄清楚逻辑位置和实际位置二者的区别。 下图显示了逆向迭代器的位置和所指的数值: 可以发现,逆向迭代器所指位置(实际位置)和所代表的的数值(逻辑位置或数...

C/C++ Map 关于insert、iterator、erase、char * key总结

本文主要讲解了STL map常用方法insert,及与之相关的pair、make_pair,同时简明阐述了iterator+erase结合使用时可能出现的问题。...

在遍历中使用 iterator/reverse_iterator 进行 Erase 的用法

众所周知,在使用迭代器遍历 STL 容器时,需要特别留意是否在循环中修改了迭代器而导致迭代器失效的情形。下面我来总结一下在对各种容器进行正向和反向遍历过程中删除元素时,正确更新迭代器的用法。首先,要明...
  • kesalin
  • kesalin
  • 2014年04月21日 20:02
  • 28088

[C/C++标准库]_[初级]_[移除反转枚举reverse_iterator]

场景 在一些业务逻辑中, 我们需要删除某个链表中的元素A, 并重新计算这个元素A后边的所有元素相对与前一个元素的值. 条件1是这个元素A必须删除, 因为这个元素A已经无效,有他存在必然影响了对整个链表...

C++ map 中的reverse_iterator

做了一个闽南师范大学OJ上的题,不想写排序,用了一下reverse_iterator,反向遍历容器 7006:学生成绩排序 Problem Description ...

逆序reverse_iterator打印

  • 2017年03月28日 10:49
  • 778B
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:STL: reverse_iterator / iterator 关系以及 erase 相关(C++)
举报原因:
原因补充:

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