g ++中for循环中的奇怪迭代器行为

时间:2012-10-20 07:51:15

标签: c++ stl

我遇到了这个奇怪的问题,下面是正常工作的代码片段。

std::multimap<long,int>::iterator dateItr = reconnQueueDates.begin();

while( dateItr!=reconnQueueDates.end()  ){
LOG_DEBUG("RUN comparision " <<cDateTime<< ", "<<dateItr->first);
if(dateItr->first <= cDateTime){
    long nextTimeout = -1;
   if( (nextTimeout = callReconnects(dateItr->second,dateItr->first))>-1){

        if(nextTimeout>0){
       reconnQueueDates.insert(std::pair<long , int>(nextTimeout, dateItr->second));
            }
            reconnQueueDates.erase(dateItr);
     LOG_DEBUG("modified the iterator ressetting");
     dateItr = reconnQueueDates.begin();
     LOG_DEBUG("resset iter");
   }//end of callreconnect if
}else{
 ++dateItr;
} //else for datetime check
 }//end of while

在此之前我在循环中使用带有++ dateItr的for循环,如下所示

 for( ;dateItr!=reconnQueueDates.end();++dateItr  ){
LOG_DEBUG("RUN comparision " <<cDateTime<< ", "<<dateItr->first);
if(dateItr->first <= cDateTime){
   long nextTimeout = -1;
   if( (nextTimeout = callReconnects(dateItr->second,dateItr->first))>-1){


            if(nextTimeout>0){
       reconnQueueDates.insert(std::pair<long , int>(nextTimeout, dateItr->second));       
             }
             reconnQueueDates.erase(dateItr);

        LOG_DEBUG("modified the iterator ressetting");
    dateItr = reconnQueueDates.begin();
    LOG_DEBUG("resset iter");
   }// callReconnect 
} // check datetime

 }// for loop

调试时我发现在更改循环内的映射后,for构造内的迭代器值仍然使用旧地址。

我正在使用ubuntu 12.04和g ++版本4.6.3。在我看来是某种编译器错误或某种优化方式。

知道它可能是哪个标志或错误。

1 个答案:

答案 0 :(得分:2)

reconnQueueDates.erase(dateItr);之后,dateItr中的迭代器无效,并且对它的任何使用都是未定义的行为。由于您的旧for循环后来都使用它,因此您的新版本“有效”这一事实纯粹是偶然的。

正确的方法是在删除该元素之前首先提取您可能仍需要的所有数据(包括下一个迭代器的位置)。例如:

std::multimap<long,int>::iterator dateItr = reconnQueueDates.begin();

while( dateItr!=reconnQueueDates.end()  )
{
  LOG_DEBUG("RUN comparision " <<cDateTime<< ", "<<dateItr->first);
  if(dateItr->first <= cDateTime)
  {
    std::multimap<long,int>::iterator nextItr = dateItr;
    ++nextItr;
    long nextTimeout = -1;
    if( (nextTimeout = callReconnects(dateItr->second,dateItr->first))>-1)
    {
      std::pair<long , int> newentry = std::make_pair(nextTimeout, dateItr->second);
      reconnQueueDates.erase(dateItr);
      if(nextTimeout>0)
      {
        reconnQueueDates.insert(newentry);
      }
      LOG_DEBUG("modified the iterator resetting");
      nextItr = reconnQueueDates.begin();
      LOG_DEBUG("reset iter");
    }//end of callreconnect if
    dateItr = nextItr;
  }
  else
  {
    ++dateItr;
  } //else for datetime check
}//end of while