我今天正在阅读有关支持双向迭代的容器的方法,这段代码是有效的:
Collection c(10,10); auto last = --c.end(); *last;
这让我想到,当提交一对双向迭代器[求,结束]到STL中的算法时,是否需要定义?end?如果是这样,结果是否可以解除引用?
即
void algo(T beg,T end){ //... auto iter = --end; //... *iter; }
解决方法
如果算法需要首先和最后由双向迭代器定义的范围,那么–last需要在与第一个相同的条件下有效 – 即范围不为空.当且仅当first == last时,范围为空.
如果范围不为空,则–last计算为引用范围中最后一个元素的迭代器,因此* – last确实也需要有效.
也就是说,并不是所有标准算法都需要专门的双向迭代器(并且不需要随机访问). prev,copy_backward,move_backward,reverse,reverse_copy,stable_partition,inplace_merge,[prev | next] _permutation.
如果你看一下其中的一些,你应该看到通常算法会减少结束范围的迭代器并取消引用结果.
正如James所说,对于容器,函数end()按值返回迭代器.对于迭代器,没有一般要求,当x是类型的右值时,– x应该是格式良好的表达式.例如,指针是双向迭代器,而函数声明为int * foo();按值返回指针,– foo()不是格式良好的表达式.碰巧的是,对于你在实现中看到的容器,end()返回一个类类型,它具有operator – 定义为成员函数,因此代码编译.它也有效,因为容器不是空的.
请注意,这方面存在差异:
auto last = --c.end();
与
auto last = c.end(); --last;
前者递减一个rvalue,而后者递减一个左值.