If I use a default constructor for an iterator, how to check if it was assigned later on?
For pointers, I could do this :
int *p = NULL;
/// some code
if(std::list<int>::iterator() == it)
But I suspect... may it's possible, that a valid iterator could pass the comparison. Better to avoid these situations. If it's impossible store the iterator by a pointer.
std::auto_ptr<std::list<int>::iterator> it;
As far as I know you must always initialize your iterators and the easiest way is to make them equal to 'container'.end() In certain cases it looks like working, we had some problems with code that worked with VC6 and stopped working with VC2010. Look at this example compiled with g++ where it works for the vector but not for the map:
# Test iterator init, compile with: g++ test-iterator.cpp -o test-iterator
#include <iostream>
#include <vector>
#include <map>
int main()
{
std::vector<int> vec;
std::vector<int>::iterator it;
if (it != vec.end())
{
std::cout << "vector inside!" << std::endl;
}
else
{
std::cout << "vector outside!" << std::endl;
}
std::map<int, int> mp;
std::map<int, int>::iterator itMap;
if (itMap != mp.end())
{
std::cout << "map inside!" << std::endl;
}
else
{
std::cout << "map outside!" << std::endl;
}
return 0;
}
In C++, uninitialized local variables can have any value i.e it contains simply garbage. That implies, you cannot check it against some well-defined value, to determine if the variable is uninitialized or not.
Not only that if the variable is not initialized and you write this:
if ( NULL == it ) // this fails
then it invokes undefined behavior.
You can't. ll you can do is compare against list end
it != mylist.end();
Most iterators don't have any global special values in the same way that all pointers can be NULL. Typically, though, you'll be working with specific containers, and if you keep one iterator per container, then you can use end()
as the sentinel value:
std::list<int> mylist;
std::list<int>::iterator it = mylist.end();
/* do stuff */
if (it == mylist.end()) { ... }
I'm not sure if insertion/deletion invalidates the end()
iterator, though, so if you're planning on modifying your container, maybe save a copy of the original end, too:
std::list<int>::iterator end = mylist.end(), it = end;
if (it == end) { ... }
Though again I'm actually not sure if it's well-defined to compare two invalid iterators (in the event that the two do get invalidated).
Maybe you should always assign a predefined value, like NULL, after creating the iterator. Later you can easily check against NULL. This will make your code more portable, as you will not depend on what starting values the uninitialized variables take at the beginning.