奇怪的迭代行为在G 中进行循环

strange iterator behavior in for loop in g++

本文关键字:循环 迭代      更新时间:2023-10-16

我得到了一个奇怪的问题,以下是正常工作的代码段。

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

在此之前,我使用的是循环中的一个循环,如下所示

 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。在我看来,某种编译器错误或某种优化这样做。

任何可能是哪个标志或错误的想法。

reconnQueueDates.erase(dateItr);之后, dateItr中的迭代器无效,任何用途都是未定义的行为。由于您的新旧 for循环之后都使用它,因此您的新版本" Works"纯粹是偶然的。

正确的方法是先提取所有可能仍需要的数据(包括下一个迭代器的位置),然后再擦除该元素。例如:

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