I found myself writing the following a lot:
int location =2;
vector<int> vec;
vector<int>::iterator it=vec.begin();
/..../
std::advance(it, location);
instead of
it= it + 5;
what is the Preferred/Recommended way ?
I found myself writing the following a lot:
int location =2;
vector<int> vec;
vector<int>::iterator it=vec.begin();
/..../
std::advance(it, location);
instead of
it= it + 5;
what is the Preferred/Recommended way ?
It depends on the iterator. it=it+5
is faster if it's supported (it's only supported on random access iterators). If you want to advance a less-capable iterator (e.g. a forward iterator, or a bidirectional iterator), then you can use std::advance
, but it's slower because it actually walks across all of the intermediate elements.
std::advance
works on non-random iterators too while the +=
version on works on random access sequences (vectors and the like).
Adding will only work with random access iterators. std::advance will work with all sorts of iterators. As long as you're only dealing with iterators into vectors, it makes no real difference, but std::advance keeps your code more generic (e.g. you could substitute a list for the vector, and that part would still work).
Edit: For those who care, the standard describes advance
and distance
as follows (§24.3.4/1):
Since only random access iterators provide + and - operators, the library provides two function templates advance and distance. These function templates use + and - for random access iterators (and are, therefore, constant time for them); for input, forward and bidirectional iterators they use ++ to provide linear time implementations.
std::adnvance
is generic - it is useful if you don't always know type of underlying container - it works in all cases.
Yet it is efficient: std::advance
will do an optimisation if it passed an RandomAccessIterator (like one from std::vector
) and will increase iterator in loop for ForwardAccessIterator (as like one in std::list
).
Use std::advance. It is just as efficient (it uses iterator traits to just do iterator addition for random access iterators), and is more general in that it works on other kinds of iterators as well.
That depends on what you need:
If you need genericity, use std::advance(it,2)
. If someone comes along and changes your std::vector
into a std::list
, the code will still compile, even though advancing now takes linear time instead of constant time.
If you need performance, use it+=2
. If someone comes along and changes your std::vector
into a std::list
, the code will fail to compile, pointing (maybe with a helpful comment) at a serious performance issue.
If you're never going to change the container (and you probably aren't), use + because it's easy to see and understand and leaves the code less cluttered.
If you think you want to change the container, OR if you are working inside a template that might be instantiated on various container types, use advance because it works with anything.
As a general rule, I don't worry about changing container types because I've found that when I do have to change a container type, I end up revisiting everywhere that container is used anyway, just to be sure I'm not doing anything that's suddenly stupid (like randomly plucking elements out of the middle of a list).