C++ 如何检查迭代器是否已初始化?
如果我对迭代器使用默认构造函数,如何检查它是否在以后分配 对于指针,我可以这样做:C++ 如何检查迭代器是否已初始化?,c++,iterator,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 ) /
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;
}
}
#包括
#包括
int main()
{
std::list::迭代器;
if(NULL==it)//此操作失败
{
std::cout你不能。你能做的就是和列表末尾进行比较
it != mylist.end();
在C++中,未初始化的局部变量可以包含任何值,即它包含简单的垃圾。这意味着,不能通过一些定义良好的值来检查它,以确定变量是否未初始化。
不仅如此,如果变量未初始化且您写入以下内容:
if ( NULL == it ) // this fails
然后它调用未定义的行为。也许在创建迭代器之后,您应该始终指定一个预定义的值,如NULL。稍后您可以轻松地检查NULL。
这将使您的代码更具可移植性,因为您将不依赖于未初始化变量在开始时采用的起始值。大多数迭代器没有任何全局特殊值,就像所有指针都可以为空一样。不过,通常情况下,您将使用特定容器,如果每个容器保留一个迭代器,然后可以使用end()
作为哨兵值:
std::list<int> mylist;
std::list<int>::iterator it = mylist.end();
/* do stuff */
if (it == mylist.end()) { ... }
尽管我也不确定比较两个无效迭代器是否定义得很好(如果这两个迭代器都无效)。if(std::list::iterator()==it)
但我怀疑…有可能,一个有效的迭代器可以通过比较。
最好避免这些情况。如果不可能,用指针存储迭代器
std::auto_ptr<std::list<int>::iterator> it;
std::自动下载它;
我在当前的标准(c++03)中找到了这一点。24.1 p 5告诉我们:
正如指向数组的常规指针保证存在
指针值指向数组的最后一个元素,因此对于任何
迭代器类型有一个迭代器值,它指向最后一个
元素。这些值被称为
超过结束值。迭代器i的值
*i
被定义为可取消引用。库从不假定
超过端点的值是可取消引用的。迭代器也可以具有
不与任何容器关联的奇异值。[示例:
在声明未初始化指针x
(与int*x;
一样)之后,
x
必须始终假定指针具有单数值。]
大多数表达式的结果对于奇异值是未定义的
唯一的例外是将非奇异值赋值给迭代器
它包含一个奇异值。在这种情况下,奇异值为
以与任何其他值相同的方式覆盖。可取消引用的值
它们总是非单数的
(强调矿山)
所以答案是:不,这是不可能的。这个问题已经在中讨论过了。其精髓是默认构造函数将迭代器初始化为一个奇异值,唯一可添加的操作是为其分配另一个迭代器值。特别是,不可能查询这种统一迭代器的值或者。因此,将迭代器初始化为特定容器的特定值是一种很好的编程实践,然后可以对其进行测试。我能想到的最好的方法是
#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;
}
#包括
#包括
#包括
#包括
命名空间空迭代器{
typedef std::map nullcntT;
nullcntT nullcontainers;
模板
typename containerT::迭代器迭代器(){
containerT*newcnt=newcontainert();
std::string cnttypename=typeid(*newcnt).name();
nullcntT::迭代器i=nullcontainers.find(cnttypename);
if(i==nullcontainers.end()){
nullcontainers.insert(make_pair(cnttypename,newcnt));
返回newcnt->end();
}否则{
删除newcnt;
return(static_cast(i->second))->end();
}
}
}
模板
typename containerT::iterator nulliterator(){返回nulliterators::iterator();}
#包括
#包括
int main(){
std::list::iterator nullinitized=nulliterator();
std::list somelist;
std::list::iterator initialized=somelist.end();
if(nullinitized==nulliterator())
std::cout())
据我所知,您必须始终初始化迭代器,最简单的方法是使它们等于“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;
}
#测试迭代器init,使用:g++Test-iterator.cpp-o测试迭代器编译
#包括
#包括
#包括
int main()
{
std::vec;
std::vector::it迭代器;
如果(it!=vec.end())
{
std::cout由于迭代器没有默认值(就像指针没有空值),在我需要对象::迭代器
的公共默认值的情况下(在创建任何实际对象之前),我创建一个伪静态变量,并使用其::end()
作为默认值
更新:这仅适用于发行版,因为在调试中(或使用\u HAS\u ITERATOR\u debuging=1
),比较运算符检查两个迭代器是否指向同一对象/容器
例如,对于vector
,我会:
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";
}
A类
{
公众:
A():myIterator1(dummyVector.end()),myIterator2(dummyVector.end()){}
//需要的迭代器
向量::迭代器myIterator1;
向量::迭代器myIterator2;
静态常数向量dummyVector;
}
#定义它\u NULL A::dummyObject.end()
void maint(){
A::dummyObject=vector();//初始化空迭代器
A A;
如果(a.myIterator1==IT_NULL)不能我使用了以下解决方案:
const MyList_t::const_iterator NullIterator(NULL);
const_iterator MyList_t::MyIterator;
然后可以进行检查:
if (NullIterator != MyIterator) {}
据我所知,没有普遍的保证
const MyList_t::const_iterator NullIterator(NULL);
const_iterator MyList_t::MyIterator;
if (NullIterator != MyIterator) {}