Sign in to follow this  
Red Ant

Quick way to get an iterator to the last element of a list

Recommended Posts

Hi y'all. Okay, before I get massacred for asking stupid questions, I have run a forum search to see if this question has been asked before, but I honestly couldn't find anything that would have helped me with this. So here goes: Basically I have a struct that I store in a list (STL). The struct looks like this
// Forward declaration.
struct MyStruct;

typedef std::list< MyStruct* > StructList;

struct MyStruct
{
    /// Loads of terribly useful data ...

    /// IMPORTANT: An iterator that I need to point to this instance's position in the list that stores MyStruct objects.
    StructList::iterator m_itMyOwnPositInTheList;
};



After I have added a MyStruct instance to the list, I want to get an iterator to the exact position at which the instance has ended up and then set that instance's itMyOwnPositInTheList member to that. It is useful for my instances to know exactly where in the list they reside, so they can later be erased quickly without having to walk the list first. So far so good. However, I'm having trouble actually obtaining this iterator ... or at least doing it without iterating the list right up to the last element (which is where I suspect push_back would place the new list element). And I can't do
StructList::iterator itLastElem = m_theList.end();
--itLastElem ;



right? Because once an iterator points to the end it's not really a valid iterator anymore (or is it?). I've also tried
StructList::iterator itLastElem = m_theList.rbegin();
++itLastElem; 



But apparently you can't convert a reverse iterator to a normal one like that. It would be really good if there was a method of putting something in a list and then getting an iterator to that exact position. Any idess?

Share this post


Link to post
Share on other sites
std::list::back()

EDIT: SGI has a good reference page if you need it in the future.

EDIT2:
Quote:
Original post by Red Ant
That would give me a reference to the last element in the list, but not an iterator pointing to that element.


Whoops. Misread the question [disturbed]

[Edited by - load_bitmap_file on June 22, 2005 7:53:47 PM]

Share this post


Link to post
Share on other sites
That would give me a reference to the last element in the list, but not an iterator pointing to that element.

Share this post


Link to post
Share on other sites
rbegin() should be an iterator pointing at the last element [iirc]. If all you want is the last element, who cares if it's a forward or reverse iterator? Calling list.erase(reverse_iterator) should still eliminate the object contained at the iterator's position. [I think]

Share this post


Link to post
Share on other sites
Ah shoot, it doesn't work. The compiler complains about not being able to convert a reverse_iterator to an iterator when I pass the thing to std::list::erase().


P.S. I think I've found a solution. It doesn't really matter if I add an element at the back or the front of the list. So if just do push_front and then get a standard iterator with std::list::begin(), I should be fine.

Share this post


Link to post
Share on other sites
Seeming you want do erase the last element of your list, isn't
StructList::pop_back()
an option?

Share this post


Link to post
Share on other sites
No, because by the time I'm going to delete a particular instance from the list it is perfectly possible that it will no longer be the last (or the first, for that matter) element in the list.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
It's ugly and maybe not portable (haven't checked), but... "--(list.end())"


#include <list>
#include <iostream>

int main() {
std::list<int> l;
for(int i = 0; i < 10; ++i) {
std::cout << "pushing " << i << "\n";
l.push_back(i);
}
std::list<int>::iterator i = --(l.end());
std::cout << "i: " << *i << std::endl;
}





Hope this helps.

Share this post


Link to post
Share on other sites
Quote:
Original post by Red Ant
No, because by the time I'm going to delete a particular instance from the list it is perfectly possible that it will no longer be the last (or the first, for that matter) element in the list.


If it might not be that last element, then why are you trying to get the last element? (Just wondering)

Here's a possible solution:
Or not

Share this post


Link to post
Share on other sites
Quote:
Original post by Red Ant
Because once an iterator points to the end it's not really a valid iterator anymore (or is it?)

Actually, it is still a valid iterator, you just aren't allowed to dereference it (punishable by undefined behavior), but decrementing it should be perfectly fine if it's at least a bidirectional iterator (and the list is non-empty), which std::lists iterators are.

Share this post


Link to post
Share on other sites
Quote:
Original post by Programmer16
Quote:
Original post by Red Ant
No, because by the time I'm going to delete a particular instance from the list it is perfectly possible that it will no longer be the last (or the first, for that matter) element in the list.


If it might not be that last element, then why are you trying to get the last element? (Just wondering)

Here's a possible solution:
Or not


Well, using my initial approach, it is the last element at the time I'm getting an iterator to it. But later, when I want to erase the element, it may no longer be the last element in the list (others may have been appended in the meantime).

Share this post


Link to post
Share on other sites
How about

int myValue = 10;
std::list<int>::iterator it = myList.insert(myList.begin(), myValue);

hold on to iterator it for later?

Share this post


Link to post
Share on other sites
Quote:
Original post by garyfletcher
How about using a map instead so you can keep a reference to any and all elements?

Because you can keep a valid reference to any and all elements of a list...?

A map is a rather different data structure.



The following solution is quoted for being the correct solution:

Quote:
Original post by DrEvil
How about

int myValue = 10;
std::list<int>::iterator it = myList.insert(myList.begin(), myValue);

hold on to iterator it for later?

That is precicely what you need to do. You can also be inserting at the .end() - or wherever you would like your item to go. Wonderful [smile].

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this