如何检查迭代器是否已初始化?

时间:2011-08-05 10:33:59

标签: c++ iterator

如果我为迭代器使用默认构造函数,如何检查它是否稍后被分配?

对于指针,我可以这样做:

int *p = NULL;
/// some code
if ( NULL == p ) {
  // do stuff
}

如何为迭代器执行上述操作? 它有可能吗?

#include <iostream>
#include <list>

int main ()
{
    std::list<int>::iterator it;

  if ( NULL == it ) // this fails
  {
      std::cout<<"do stuff" << std::endl;
  }
}

11 个答案:

答案 0 :(得分:17)

我设法在当前标准(c ++ 03)中找到了这个。 24.1 p 5告诉:

  

就像指向数组的常规指针一样,确保存在   指针值指向数组的最后一个元素,因此对于任何   迭代器类型有一个指向过去的迭代器值   相应容器的元素。调用这些值   过去的价值观。迭代器的值i为其表达式   我定义的被称为可解除引用。图书馆永远不会假设   过去的价值是可以解除引用的。 迭代器也可以   与任何容器无关的奇异值。 [示例:   在声明未初始化的指针x之后(与int x;一样),   必须始终假定x具有指针的奇异值。 ]   大多数表达式的结果未定义为奇异值;该   唯一的异常是将非奇异值赋给迭代器   具有奇异值。在这种情况下,奇异值是   以与任何其他值相同的方式覆盖。可解除引用的值   总是非单数的。

(强调我的)

所以答案是:不,这是不可能的。

答案 1 :(得分:3)

大多数迭代器没有任何全局特殊值,就像所有指针都可以为NULL一样。但是,通常情况下,您将使用特定容器,如果每个容器保留一个迭代器,则可以使用end()作为标记值:

std::list<int> mylist;
std::list<int>::iterator it = mylist.end();

/* do stuff */

if (it == mylist.end()) { ... }

我不确定插入/删除是否会使end()迭代器失效,所以如果您计划修改容器,也可以保存原始结尾的副本:

std::list<int>::iterator end = mylist.end(), it = end;

if (it == end) { ... }

虽然我实际上不确定它是否被定义为比较两个无效的迭代器(如果这两个迭代器失效)。

答案 2 :(得分:1)

在C ++中,未初始化的局部变量可以具有任何值,即它只包含垃圾。这意味着,无法根据一些明确定义的值进行检查,以确定该变量是否未初始化。

不仅如果变量未初始化并且你写了这个:

if ( NULL == it ) // this fails

然后它调用未定义的行为。

答案 3 :(得分:1)

此问题已在Stackoverflow中得到处理。精髓是默认构造函数将迭代器初始化为奇异值,并且唯一可添加的操作是为其分配另一个迭代器值。特别是不可能查询这种单元化迭代器的值。因此,将迭代器初始化为特定容器的特定值是一种很好的编程习惯,然后可以对其进行测试。

答案 4 :(得分:1)

由于迭代器没有默认值(就像指针有NULL),在我需要Object::iterator的公共默认值的情况下(在创建任何实际的Object之前),我创建了一个虚拟静态变量并使用其::end()作为默认值。

更新:这仅适用于Release,因为在DEBUG中(或使用_HAS_ITERATOR_DEBUGGING=1)比较运算符检查两个迭代器是否指向同一个对象/容器。

例如对vector<int>我会这样做:

class A
{
public :
    A() :  myIterator1(dummyVector.end()), myIterator2(dummyVector.end()) {}
    // needed iterators
    vector<int>::iterator myIterator1;
    vector<int>::iterator myIterator2;

    static const vector<int> dummyVector;
}

#define  IT_NULL A::dummyObject.end()

void maint() {
    A::dummyObject = vector<int>(); // initialize the Null iterator

    A a;
    if(a.myIterator1 == IT_NULL) cout << "Iterator not yet initialized";
}

答案 5 :(得分:0)

你做不到。你能做的就是与列表结尾进行比较

it != mylist.end();

答案 6 :(得分:0)

在创建迭代器之后,也许你应该总是分配一个预定义的值,比如NULL。稍后您可以轻松检查NULL。 这将使您的代码更具可移植性,因为您不会依赖于未初始化变量在开始时采用的起始值。

答案 7 :(得分:0)

if(std::list<int>::iterator() == it)

但我怀疑......有可能,有效的迭代器可以通过比较。 最好避免这些情况。如果不可能通过指针存储迭代器。

 std::auto_ptr<std::list<int>::iterator> it;

答案 8 :(得分:0)

我能想到的最好的方法是

#include <utility>
#include <map>
#include <typeinfo>
#include <string>



namespace nulliterators {

typedef std::map<std::string, void*> nullcntT;
nullcntT nullcontainers;

template<class containerT>
typename containerT::iterator iterator() {
  containerT* newcnt = new containerT();
  std::string cnttypename = typeid(*newcnt).name();
  nullcntT::iterator i = nullcontainers.find(cnttypename);
  if (i==nullcontainers.end()) {
    nullcontainers.insert(make_pair(cnttypename, newcnt));
    return newcnt->end();
   }else{
    delete newcnt;
    return (static_cast<containerT*>(i->second))->end();
  }
}

}
template<class containerT>
typename containerT::iterator nulliterator() { return nulliterators::iterator<containerT>(); }


#include <list>
#include <iostream>


int main(){

  std::list<int>::iterator nullinitized = nulliterator< std::list<int> >();
  std::list<int> somelist;
  std::list<int>::iterator initialized = somelist.end();

  if (nullinitized == nulliterator< std::list<int> >())
    std::cout << "nullinitized == nulliterator< std::list<int> >()\n";  //true
   else
    std::cout << "nullinitized != nulliterator< std::list<int> >()\n";

  if (initialized == nulliterator< std::list<int> >())
    std::cout << "initialized == nulliterator< std::list<int> >()\n";
   else
    std::cout << "initialized != nulliterator< std::list<int> >()\n";  //true

  return 0;
}

但它并不是一个安全的解决方案(因为它依赖于nullcontainers中的非const全局容器)。

答案 9 :(得分:0)

据我所知,你必须始终初始化你的迭代器,最简单的方法是使它们等于'container'.end() 在某些情况下,它看起来像工作,我们遇到了一些问题,代码与VC6一起工作,并停止使用VC2010。看看这个用g ++编译的例子,它适用于矢量,但不适用于地图:

# 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;
}

答案 10 :(得分:0)

我使用了以下解决方案:

const MyList_t::const_iterator NullIterator(NULL);
const_iterator MyList_t::MyIterator;

然后可以检查:

if (NullIterator != MyIterator) {}