Peek the next element in STL container

2019-01-23 13:54发布

问题:

is it possible to peek next element in a container which the iterator currently points to without changing the iterator?

For example in std::set,

int myArray[]= {1,2,3,4};
set <int> mySet(myArray, myArray+4);
set <int>::iterator iter = mySet.begin();

//peek the next element in set without changing iterator.

mySet.erase(iter); //erase the element if next element is n+1

回答1:

Not with iterators in general. An iterator isn't guaranteed to be able to operate non-destructively. The classic example is an Input Iterator that actually represents an underlying input stream.

There's something that works for this kind of iterator, though. A Forward Iterator doesn't invalidate previous copies of itself by the act of moving forward through the collection. Most iterators (including those for STL collections) are at least Forward Iterators, if not a more functional version- only Input Iterators or Output Iterators are more restricted. So you can simply make a copy of your iterator, increment the copy and check that, then go back to your original iterator.

So your peek code:

set <int>::iterator dupe = iter;
++dupe;
// (do stuff with dupe)


回答2:

C++0x adds a handy utility function, std::next, that copies an iterator, advances it, and returns the advanced iterator. You can easily write your own std::next implementation:

#include <iterator>

template <typename ForwardIt>
ForwardIt next(ForwardIt it, 
               typename std::iterator_traits<ForwardIt>::difference_type n = 1)
{
    std::advance(it, n);
    return it;
}

You can use this in your example like so:

if (iter != mySet.end() && next(iter) != mySet.end() && *next(iter) == *iter + 1)
    mySet.erase(iter);


回答3:

set <int>::iterator iter2 = iter;
++iter2;
int peekedValue = *iter2;


回答4:

You can always make a copy of the iterator and advance the copy:

set <int>::iterator iter = mySet.begin();
set <int>::iterator iterCopy = iter;
iterCopy++;
if (*iterCopy == something)
  mySet.erase(iter);

But beware that iterCopy may no longer be valid once you erase iter.



回答5:

for sequence containers (vector, deque, and list) you can call front which will give you a peek (more info on the lower part of this link).



回答6:

This will not work for std::set as its nature does not allow for the [] operator, but for containers that do, you can do:

std::vector<int> v;
v.push_back(3);
v.push_back(4);
std::vector<int>::iterator it = v.begin(); 
std::cout << v[it - v.begin() + 1];

But this could be dangerous if it points to the last element in the container; but the same applies to the solution above. E.g. you'll have to make checks in both cases.



标签: c++ stl iterator