调用reverse_iterator的base成员函数可以产生“对应的”iterator。
vector<int> v;
v.reserve(5);
for(int i = 0;i < 5; ++ i) { // 向vector插入1到5
v.push_back(i);
}
vector<int>::reverse_iterator ri = // 使ri指向3
find(v.rbegin(), v.rend(), 3);
vector<int>::iterator i(ri.base()); // 使i和ri的base一样
结果如下:
end()与rbegin()、begin()与rend()不在同一个位置,这是为了保证区间保持左开右闭的原则;即:[begin(), end()) 与 [rbegin(),rend())两个左闭右开区间都可以表示容器的元素范围。由rbegin和end、rend和rbegin()的定义可以看出,逆向迭代器总是在对应正向迭代器的前一个位置。
删除、插入函数需要传入正向迭代器,所以需要用逆向迭代器的成员函数base()将其转换为iterator。
插入
由于reverse_iterator遍历的顺序是自右向左,而且插入操作会将新元素插入到ri位置,并且将原先ri位置的元素移到遍历过程的“下一个”位置(插入元素的左侧),假设想在ri处插入元素99,结果应该如下:
删除
如果要删除ri指向的元素,就不能直接使用i了,因为i与ri不是指向同一个元素。因此,你要删除的是i的前一个元素。
vector<int> v;
... // 向v插入1到5,同上
vecot<int>::reverse_iterator ri =
find(v.rbegin(), v.rend(), 3); // 同上,ri指向3
v.erase(--ri.base()); // 尝试删除ri.base()前面的元素;
但使用上述代码,对vector编译一般不通过(视具体的STL实现对vector迭代器的实现而定,一般为指针)。C和C++都规定了不能直接修改函数返回的指针。
要移植从一个由reverse_iterator指出的位置删除元素时,应该尽量避免修改base的返回值。取而代之,需要先增加reverse_iterator的值,然后再调用base!(因为reverse_iterator总在base()位置前一个位置,++reverse_iterator则base()处左移,相当于--)
v.erase((++ri).base()); // 删除ri指向的元素;
因为这个方法适用于所有的标准容器,这是删除一个由reverse_iterator指出的元素时首选的技巧。