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
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- 解析C++中派生的概念以及派生类成员的访问属性
- C++ Custom Control控件向父窗体发送对应的消息