您的位置:首页 > 编程语言 > C语言/C++

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

2015-11-17 17:31 656 查看

反向迭代器

相信大家对正向迭代器应该都很熟悉,然而对于反向迭代器的使用确是有几处需要注意的地方,在此记录一下。先看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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息