tags:

views:

215

answers:

5

Hey,

i just want to check, if the iterator points on an object in a list.

What's the cmd?

Thank you. :)

SkyThe

EDIT:

Hmm,.. ok i tried it. Now there is a Error: "Expression: list iterators incompitable"

Maybe some code:

#include <list>
list<obj> list;
list<obj>::iterator it;

if(it != list.end()){ //here the error pops up when i debug
  vShowStatus();
}else{
  cout << "...";
}
+1  A: 

Read about C++ Iterators

En example:

vector<int> the_vector;
vector<int>::iterator the_iterator;


for( int i=0; i < 10; i++ ) the_vector.push_back(i);
int total = 0;
the_iterator = the_vector.begin();
while( the_iterator != the_vector.end() ) {
  total += *the_iterator;
  ++the_iterator;
}

cout << "Total=" << total << endl;
Filip Ekberg
How to check it in a if condition?if( the_iterator != the_vector.end() )?
SkyThe
To me, your second loop looks more suited to a for loop, rather than a while loop. I don't know many details but I thought you used a for loop when you know before the loop starts how many times it should loop.
Dom
@Dom: In C/C++ the `for` loop is not that different from a `while`. I would also prefer a for loop, not because you know the number of iterations, but rather because you have an 'iteration step' (the increment), using a for loop will make clearer that incrementing the iterator is part of the loop control and not the actual logic: `for ( std::vector<int>::const_iterator it = the_vector.begin(), end = the_vector.end(); it != end; ++it ) { total += *it; }` seems to express clearer that incrementing `total` is the operation that is performed in the loop
David Rodríguez - dribeas
A: 
if (it!=collection.end()) std::cout << "Iterator points to data" << std::endl;
else                      std::cout << "Iterator does not point to data" << std::endl;
Patrick
That's it. Thanks :)
SkyThe
will it work for the following: it = collection.begin(); it--; ??
Donotalo
May-be you should also add a note that the iterator is supposed to be initialized, and preferably point into the same list you are comparing against. @Donotalo: That is just undefined behavior.
visitor
Wouldn't this only work if the iterator is only being looped from collection.begin() to collection.end(). If something went wrong and the iterator pointed to something else entirely (a different list of the same type), wouldn't this code just say it points to data (because it doesn't point to the end)?
Dom
... or if you iterate in reverse order from `rbegin()` to `rend()`... this test is quite vague... but I guess not vaguer than the question itself
David Rodríguez - dribeas
@David: `list::rbegin()` doesn't return a `list::iterator` anyway.
MSalters
@MSalters, true I don't know what I was thinking about
David Rodríguez - dribeas
Alas, this answer gets the best answer.
Donotalo
@Donotalo, I was trying to give a an answer that makes sense in most cases. Of course decreasing the iterator before its begin makes it invalid as well, but if you want to protect you against every possible case (even memory overwrites), the only thing you can do is loop over the list and compare all values of the loop iterator with the given iterator (and even then I'm not sure that it's guaranteed to compare a valid operator with an invalid operator).
Patrick
OK, now I see this. But I think the OP wanted to know a simple checking that covers all possible cases. @ Patrick
Donotalo
+6  A: 

You can't. There's no method to check that. You must structure your code so that your iterator is between list.begin() and list.end().

Use iterator this way:

for (std::list<int>::const_iterator it = myList.begin(); it != myList.end(); ++it)
         cout << *it << " ";

You can't compare [EDIT] list iterators with relational operators (<, >, <=, >=), so when you use an iterator outside a for loop, then you must always check if you go outside the bounds by comparing to begin() (if your going backward with --it) or with end() (if your going forward with ++it).

std::list<int>::const_iterator it = ... // initialized with some CORRECT value
// going backward
while (true)
{
    cout << *it;
    if (it == list.begin())
        break;
    --it;
}
// going forward
while (true)
{
    cout << *it;
    ++it;
    if (it == list.end())
        break;
}
// or simplier
while (it != list.end())
{
    cout << *it;
    ++it;
}

If, for some reason, you really need a check, then you can loop through the list and check if any of the iterators is equal to yours. But this may have a considerable impact on performance, so use it only in debug or/and in tests.

Stefan
[You can't compare iterators with relational operators]. Sure you can. see: http://www.cplusplus.com/reference/std/iterator/RandomAccessIterator/
KitsuneYMG
I was talking about iterators returned by std::list. They are not RandomAccessIterators, so you can't compare them this way.
Stefan
A: 

You have an uninitialized iterator there. I don't think there is a way to test if it is uninitialized. (Always initialize your variables to avoid this problem in the first place.)

You can determine if an initialized iterator points to something in a list by comparing it to the end iterator of the same list.

visitor
A: 

The standard has this to say about uninitialized iterators (24.1.5):

Iterators can also have singular values that are not associated with any container. For example, after the declaration of an uninitialized pointer x (as with int* x;), x must always be assumed to have a singular value of a pointer. Results of most expressions are undefined for singular values; the only exception is an assignment of a non-singular value to an iterator that holds a singular value. In this case the singular value is overwritten the same way as any other value.

So, no. Since the only thing you can do with an uninitialized (or invalidated) iterator is to make it a valid iterator, there is no way to test if you have one. Always initialize the iterators that you declare (also limit the scope you use them in), and make sure you don't continue to use the iterator after an invalidating operation.

It is possible, though, that the specific implementation of your compiler's SC++L keeps track of uninitialized iterators, and throws an error of the kind you are seeing if you do something illegal with the iterator. This is in no way a guaranteed result, though.

UncleBens