2012-01-25 77 views
8
Driver::~Driver() 
{ 
    AutoCritSec acsDriverList(m_csDriverList,true); 
    DRIVERLIST::iterator it = m_DriverList.begin(); 
    for(;it!=m_DriverList.end();it++) 
    { 
     if (it->second == this) 
     { 
      m_DriverList.erase(it); 
      it = m_DriverList.begin(); 
     } 
    } 
} 

当我在visual studio 2003中编译我的程序时,我的程序表现良好。但是当我在2010年做的一样,然后同时关闭应用程序,我得到这样map/set迭代器不可递增map/set迭代器不可递增

Expression:map/set iterator not incrementable 

一些错误,当我按下忽略这一点,我得到

Expression:"standard c++ library out of range" && 0 

是否有任何人有任何的想法是什么在这里:我会非常感激任何人的任何建议。吨的感谢和温暖的祝福。

回答

12

如果this是列表中的唯一元素,则会超出列表的末尾。

从列表中删除this后,您重置it = m_DriverList.begin();。这可以。然后评估循环表达式(i++ from for语句),这会导致it超出范围的末尾。

推进迭代器超过容器的末端会导致程序显示未定义的行为。最近版本的Visual C++有助于检测程序的调试版本中的许多常见迭代器错误,并提出断言来帮助您解决它们。

您可以通过删除循环表达式,并将其移入一个else陈述解决问题:

while (it != m_DriverList.end()) 
{ 
    if (it->second == this) 
    { 
     m_DriverList.erase(it); 
     it = m_DriverList.begin(); 
    } 
    else 
    { 
     ++it; 
    } 
} 

虽然,每次你删除一个元素是相当浪费重启迭代。考虑使用由调用返回的迭代器,而不是使用到erase

it = m_DriverList.erase(it); 
+0

擦的好推荐/删除。在这种特殊情况下,m_DriverList显然是成对的容器,或者是某种类型的映射,因为测试就在它上面 - >秒。而不是std :: remove,它需要std :: remove_if与lambda函数或比较函数。 –

+0

如果容器是一个映射(问题标题,访问成员'second'),那么我不认为可以应用* erase-remove *成语。惯用法与您所使用的while循环相似,但不是重新开始迭代,而是复制并推进迭代器,然后擦除当前位置。 –

+0

@DavidRodríguez-dribeas @MarkTaylor:好的;我被变量名称中的“List”分心了。在C++ 11中,'erase'将迭代器返回到下一个元素(或者如果没有下一个元素,则返回到一个尾部),并且Visual C++ 2010支持这一点。 –

6

正确擦除成语关联容器如下:

for (auto it = container.begin(); it != container.end() /* not hoisted */; /* no inc. */) 
{ 
    if (delete_condition) 
    { 
     container.erase(it++); 
    } 
    else 
    { 
     ++it; 
    } 
}