关闭

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

标签: C++STLiteratorreverse_iteratorerase
208人阅读 评论(0) 收藏 举报
分类:

    反向迭代器

    相信大家对正向迭代器应该都很熟悉,然而对于反向迭代器的使用确是有几处需要注意的地方,在此记录一下。先看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

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:41977次
    • 积分:1797
    • 等级:
    • 排名:千里之外
    • 原创:145篇
    • 转载:0篇
    • 译文:0篇
    • 评论:4条
    最新评论