在VS,UNIX / Linux中删除之后,STL迭代器会发生什么?

请考虑以下情况:

map(T,S*) & GetMap(); //Forward decleration map(T, S*) T2pS = GetMap(); for(map(T, S*)::iterator it = T2pS.begin(); it != T2pS.end(); ++it) { if(it->second != NULL) { delete it->second; it->second = NULL; } T2pS.erase(it); //In VS2005, after the erase, we will crash on the ++it of the for loop. //In UNIX, Linux, this doesn't crash. }//for 

在我看来,在VS2005中,在“擦除”之后,迭代器将等于end(),因此在尝试增加它时会崩溃。 这里介绍的行为编译器之间真的有区别吗? 如果是这样,“擦除”之后的迭代器在UNIX / Linux中等于什么?

谢谢…

Solutions Collecting From Web of "在VS,UNIX / Linux中删除之后,STL迭代器会发生什么?"

是的,如果你擦除一个迭代器,那个迭代器会得到一个所谓的奇异值 ,这意味着它不再属于任何容器。 你不能增加,减少或读出/写入它了。 做这个循环的正确方法是:

 for(map<T, S*>::iterator it = T2pS.begin(); it != T2pS.end(); T2pS.erase(it++)) { // wilhelmtell in the comments is right: no need to check for NULL. // delete of a NULL pointer is a no-op. if(it->second != NULL) { delete it->second; it->second = NULL; } } 

对于在擦除一个迭代器时可能使其他迭代器无效的容器, erase将返回下一个有效的迭代器。 然后你就这样做了

 it = T2pS.erase(it) 

这是如何工作的std::vectorstd::deque ,但不适用于std::mapstd::set

在迭代器上调用erasestd::map ,它将失效。 这意味着你不能使用它。 试图使用它(例如通过增加它)是无效的,并可能导致任何事情发生(包括崩溃)。 对于一个std::map ,在迭代器上调用erase并不会使任何其他迭代器(例如)在这个调用之后(只要it不是T2pS.end()T2pS.end() ,它将是有效的:

 T2pS.erase( it++ ); 

当然,如果你使用这种方法,你不会在for循环中无条件地增加it

在这个例子中,为什么要在for循环中擦除呢? 为什么不在循环结尾调用T2pS.clear()呢?

另一方面,它看起来像是在地图的右边有一个原始指针,但是地图看起来像是拥有指向的对象。 在这种情况下,为什么不使地图右侧的某种智能指针,如std :: tr1 :: shared_ptr?

[顺便说一句,我没有看到任何模板参数map 。 你是否在本地命名空间中键入了一个特定的std::map实例作为map ?]

看到这个 :

 for (i = v.begin(); i != v.end(); ) { //... if (erase_required) { i = v.erase(i); } else { ++i; } } 

我想如果你修改集合,你的迭代器失效。 正如你发现的那样,你不能依靠这种行为。