STL中const_iterator、reverse_iterator转换为iterator

本文同步自(如浏览不正常请点击跳转):https://zohead.com/archives/stl-const-reverse-iterator/

STL中的容器类(Container)一般提供了4个迭代器:iterator、const_iterator、reverse_iterator、const_reverse_iterator,对于 container<T> 而言,其中 const_iterator 相当于 const T *,const_iterator 指向的元素不能做修改操作。

STL 容器的 begin() 和 end() 默认都提供了 iterator 和 const_iterator 的迭代器,相应的 rbegin() 和 rend() 则也分别提供了 reverse_iterator 和 const_reverse_iterator 的迭代器用于从容器的尾端反向遍历。

最近写的代码中刚好要用到 const_iterator 迭代器,发现由于 STL 提供的一些容器操作函数像 insert、erase 的参数必须为 iterator,这时就不能用 const_iterator 做参数(不能直接转换),以下为个人经验结果。

1、const_iterator 转换为 iterator:

iterator 可以隐式转换为 const_iterator,但反过来就不行,就算祭出强制类型转换的杀招应该也会编译报错,这是可以用折中的办法解决:

vector<sss> v_test;
vector<sss>::iterator i_test;
vector<sss>::const_iterator c_test;
...
c_test = ....
...
i_test = v_test.begin();
advance(i_test, distance<vector<sss>::const_iterator>(i_test, c_test));

i_test 指向第一个元素,先通过 distance 得到 c_test 和 i_test 的偏移量,然后用 advance 将 i_test 往后移对应的偏移量即可。注意 distance 的模板类型必须为 const_iterator 类型,否则按照 STL 的默认类型推导,distance 中的 i_test 和 c_test 类型不同还是会出现编译报错。

当然如果你想偷懒简单点,也可以这样写,道理是一样的,这时类型推导就显得很好用了:

i_test = v_test.begin() + (c_test - v_test.begin());

2、reverse_iterator 转换为 iterator:

对于 reverse_iterator 可以调用 base() 得到 “与之对应” 的 iterator(与上面的环境一样):

vector<sss> v_test;
vector<sss>::iterator i_test;
vector<sss>::reverse_iterator r_test;
...
r_test = ....
...
i_test = r_test.base();

但需要注意的是由于 STL 的 begin() 和 end()、rbegin() 和 rend() 是两个半闭合的区间,end() 并不是最后一个元素,rend() 也不是第一个元素,因此 end() 和 rbegin()、rend() 和 begin() 之间都是差了一个元素的。我们来看看 STL 标准上 base() 的说明:

The base iterator is an iterator of the same type as the one used to construct the reverse_iterator, but pointing to the element next to the one the reverse_iterator is currently pointing to (a reverse_iterator has always an offset of -1 with regards to its base iterator).

也就是 reverse_iterator 的 base() 返回的元素都是 reverse_iterator 所指向元素的下一个元素,这也是前面 “与之对应” 加引号的原因。因此在使用时要特别注意,例如如果要删除 reverse_iterator 指向的元素就需要这样(因为 erase 必须要 iterator 类型的参数):

v_test.erase((++r_test).base());

3、关于随机访问容器:

STL 中随机访问容器是一个迭代器类型为随机访问迭代器的可逆容器,它提供常量缓冲时间来访问随机元素。而可逆容器是一个有双向迭代器的前向容器,它可以向后向后迭代通过容器。

常用到的顺序容器是将单一类型的元素聚集起来,然后根据位置来存储和访问这些元素。顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。

平时经常用的 string、vector、deque 之类就是典型的随机访问容器,map、set、list 之类的就不是。

因此需要注意 STL 中的 sort 等函数的参数必须是随机访问迭代器,所以对 map、set、list 等容器是无效的。

以上为个人见解,有任何问题欢迎指正交流咯 ^_^。

发表评论

电子邮件地址不会被公开。 必填项已用*标注


*