locked
std::list<>::iterator null pointer incompatibility RRS feed

  • Question

  • I'm using the STL. 

    The following generates an error at runtime:
    std::list<string>::iterator it = NULL;
    
    if (it!=NULL) {}; // error here
    
    
    Why could that happen once iterators are pointers ?

    Should I use std::list<>::pointer instead ? How will I point to the list elements then ?

    Tuesday, June 23, 2009 6:43 AM

Answers

  • If you have a valid iterator i, you can get a pointer to the object it refers to with:

    &*i

    Of course, this is not valid for an iterator equal to some container's end(), because it is undefined to dereference such an iterator.


    Doug Harrison (Visual C++ MVP)
    Tuesday, June 23, 2009 12:53 PM

All replies

  • While pointers are iterators, iterators in general are not pointers. Unlike pointers, there is no "null" iterator. The closest thing would be an iterator equal to some container's end(), and note that this can be a transient relationship, as the value of end() can change with additions and deletions to the container.

    Doug Harrison (Visual C++ MVP)
    Tuesday, June 23, 2009 6:52 AM
  • Ok.

    So I suppose it is better for me using pointer instead. But how do I do that ? How do I assing the pointer to point to the list element in a normal way ?
    Can't find the documentation on that one..

    Thank you !

    Tuesday, June 23, 2009 6:59 AM
  • If you have a valid iterator i, you can get a pointer to the object it refers to with:

    &*i

    Of course, this is not valid for an iterator equal to some container's end(), because it is undefined to dereference such an iterator.


    Doug Harrison (Visual C++ MVP)
    Tuesday, June 23, 2009 12:53 PM
  • I suppose it is possible to this:

    i = my_list.end();

    to tell i to point somewhere similar to NULL

    Tuesday, June 23, 2009 1:51 PM
  • Yes, that's why I said what I said in my first reply, "Unlike pointers, there is no "null" iterator. The closest thing would be an iterator equal to some container's end(), and note that this can be a transient relationship, as the value of end() can change with additions and deletions to the container." It should also be understood that such an iterator can be compared only to other iterators on that container. That's another difference from a null pointer.


    Doug Harrison (Visual C++ MVP)
    Tuesday, June 23, 2009 3:27 PM
  • Ouch! :)
    That seems to be unsafe..

    But is it really possible to declare a pointer to an iterator ?
    I used to try it, it seems to be not working properly..

    The thing is I need to have something like additional pointers pointing to some elements in the list.


    Thanks!

    Tuesday, June 23, 2009 3:46 PM
  • We haven't been talking about "pointers to iterators". And while you can create them, there isn't any point in doing so.


    Doug Harrison (Visual C++ MVP)
    Tuesday, June 23, 2009 4:01 PM
  • But how is it possible to use the iterators without additional members then ?
    There is a need to know if an iterator has been set or if it is empty, null etc.

    May be it is possible to do the following:

    list<>:: pointer ptr = NULL;

    ptr = &*i;
    ...
    if(ptr)
    while(&*i != ptr)
    ...

    But it seems not to be cool..

    Tuesday, June 23, 2009 4:11 PM
  • No, that doesn't make any sense.

    It is entirely up to you to keep track of whether or not an iterator is valid or not, in almost exactly the same way it is up to you to keep track of whether or not an int is valid or not. For both types of data, there is no universal singular value. The difference is that each container provides a sort of singular value specific to itself in the form of end(). The iteration pattern for a standard container is:

    for (Container::iterator i = c.begin(); i != c.end(); ++i)
       ...




    Doug Harrison (Visual C++ MVP)
    Tuesday, June 23, 2009 8:00 PM
  • Yes, I understand that..

    I mean, let say there is a custom list. There you can have some additional pointers pointing either to some elements in the list or NULL. They are not iterators. Once suitable element joins the list an appropriate pointer assigned otherwise it is NULL. As far as I remember this kind of list called "table", may be I'm wrong. The idea is I need to have a list with some additional pointers somewhere in its middle. And basically then I can iterate from the beginning up to defined position for example.

    list<> mylist;
    list<>::pointer lptr;
    
    ...add some elements to the list
    
    lptr = &mylist.back();
    
    ...add some more elements
    
    for(; lptr != &*(--mylist.end()); mylist.pop_back()) {};
    

    The above works and does what I'm for. However, I suppose there is any better solution..

    Wednesday, June 24, 2009 8:55 AM
  • Another approach would be to use integer indexes, with -1 representing the singular value, and size() substituting for end(). Note that the expression --mylist.end() is undefined for an empty list.


    Doug Harrison (Visual C++ MVP)
    Saturday, June 27, 2009 6:21 PM