STL

《Effective STL》

28《正确理解由reverse_iterator的base()成员函数所产生的iterator的用法》

Posted by Liangjf on April 9, 2019

条目二十八《正确理解由reverse_iterator的base()成员函数所产生的iterator的用法》

迭代器的种类一共有四种,上面已经说过了。这里就不再次写出来。

这一个条目主要是reserce_iterator和iterator的转换。可以使用base()函数来把前者转换为后者。

比如在拥有reserve_iterator,但需要用到插入,删除成员函数,那么这两个是不接受reserve_iterator作为参数的,所以需要转换为iterator再进行下一步的插入和删除元素。

以上代码得到的实际元素排布如下图:

首先应了解,通过base()得到的迭代器,只是把rbegin 和rend位置调换,然后整体向右移动一个地址。所以这样会造成调用base()迭代器指向的位置不一致,iterator会比reserve_iterator右移一位。

插入操作 这样在插入的时候,因为是在迭代器指向前插入新元素的,所以两种迭代器的结果是一样的。

删除操作 由于调用base()后的迭代器指向不一样,所以删除元素的结果是不一样的。

解决方法:

  • 1.看起来“可行的”。

    vertor v; ... vector::_revervse_iterator tr = find(v.rbegin(), v.rend(), 3); v.erase(--tr.bases());

这种方法在vwctor和string的时候有些stl实现会编译出错。因为它们的底层实现是迭代器是一根指针。

C和C++都规定了从函数返回的指针不应该被修改

  • 2.最优的方法。

vertor v; ... vector::_revervse_iterator tr = find(v.rbegin(), v.rend(), 3); v.erase((++tr).bases());

这种方法是,既然base()后你迭代器的指向后移一位,那么我就先往前一位再调用base(),这样得到的迭代器就是reserve_iterator和iterator的指向是一致的。

通过base()函数可以得到一个与reverse_iterator“相对应的”iterator的说法并不准确。对于插入操作,这种对应关系确实存在;但是对于删除操作,情况却并非如此简单。当你将一个reverse_iterator转换成iterator的时候,很重要的一点是,你必须很清楚你将要对该iterator执行什么样的操作,因为只有在此基础上,你才能够确定这个iterator是不是你所需要的iterator。