tags:

views:

197

answers:

4

Hi,

Is there a reason that the STL does not provide functions to return an iterator into a container via an index?

For example, let's say I wanted to insert an element into a std::list but at the nth position. It appears that I have to retrieve an iterator via something like begin() and add n to that iterator. I'm thinking it would be easier if I could just get an iterator at the nth position with something like, std::list::get_nth_iterator(n).

I suspect I have misunderstood the principles of the STL. Can anyone help explain?

Thanks BeeBand

+11  A: 

You can use advance() from the <iterator> header:

list<foo>::iterator iter = advance(someFooList.begin(), n);

list<foo>::iterator iter = someFooList.begin();

std::advance( iter, n);

If the iterator supports random access (like vector) it'll work quite efficiently, if it only supports increasing (or decreasing) the iterator, like list, it'll work but only as well as can be.

Michael Burr
The code above generates a syntax error because std::advance() returns void. The code should read `iter = someFooList.begin(); advance(iter, n);`
BeeBand
I'm sorry - I posted in haste just before a meeting, and like nearly all code that I don't actually compile, this was wrong. I've corrected it. std::advance() takes a reference to an iterator that gets updated rather than returning a new iterator. It's probably specified like that to reasonably support things like input-only iterators (since in that case, if `advance()` took a value parameter rather than a reference, the iterator passed to `advance()` would return a different item when dereferenced after `advance()` returns. The interface `advance()` uses makes that a bit more evident).
Michael Burr
+4  A: 

std::list is a linked list. So it does not support random access. To get to the nth position in the list, you have to start at the beginning and move through all the nodes until you arrive at n. This is pretty expensive (O(n)), and thus it's bad to have a method that does not suggest this expense. get_nth_iterator(n) implies getting the iterator that points to the nth node is cheap.

std::vector of course supports this directly with the [] operator, because the datastructure supports random access and so this is very inexpensive for it.

Matt Greer
Actually if `get_nth_iterator()` were a free function, then the implication is that it might not be efficient. Consider `std::vector<int> n; ... n.erase(std::remove(n.begin(), n.end(), 12), n.end());`
D.Shawley
Oops... sorry... didn't realize that `get_nth_iterator()` was a proposed method of `std::list`.
D.Shawley
+2  A: 

std::list isn't random-access container, so there is no reason for accessing n-th element. if you need this, consider using std::vector instead..

Yossarian
There are, unfortunately, sometimes good reasons to access the nth element of a list. Vectors and lists are efficient at different things, and sometimes you have to do different things with the same data structure.
David Thornley
+1  A: 

Generally, anything that might be costly is made a bit clumsy, so you won't do it by accident. Using your example, with a container that provides random access iterators it would be simply container.begin()+n, but for an std::list (which provides a forward iterator) you'd need to use list.begin() followed by advance().

If you want to get the Nth iterator, chances are that you just shouldn't be using std::list in the first place. Then again, if you started that sentence at "chances", it would remain nearly as true...

Jerry Coffin