【问题标题】:map/set iterator not incrementablemap/set iterator not incrementable映射/设置迭代器不可递增映射/设置迭代器不可递增
【发布时间】:2012-01-25 03:31:46
【问题描述】:
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 年做同样的事情时,然后在关闭应用程序时出现一些错误,例如

Expression:map/set iterator not incrementable

当我按下忽略这个时,我得到了

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

有没有人知道这里发生了什么:我将非常感谢任何人的任何建议。非常感谢和热烈的祝福。

【问题讨论】:

    标签: c++ visual-c++


    【解决方案1】:

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

    从列表中删除 this 后,您将重置 it = m_DriverList.begin();。这可以。然后对循环表达式求值(for 语句中的i++),这会导致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);
    

    【讨论】:

    • 擦除/删除的好建议。在这种特殊情况下,m_DriverList 显然是对的容器或者是某种地图,因为测试是在它上面-> 第二个。代替 std::remove 它将需要带有 lambda 或比较函数的 std::remove_if。
    • 如果容器是地图(问题标题,访问成员second)那么我认为不能应用erase-remove习语。惯用语类似于您拥有的 while 循环,但不是重新开始迭代,而是复制并推进迭代器,然后擦除当前位置。
    • @DavidRodríguez-dribeas @MarkTaylor:很好的收获;我被变量名中的“列表”分心了。在 C++11 中,erase 将迭代器返回到下一个元素(如果没有下一个元素,则返回到最后一个元素),Visual C++ 2010 支持这一点。
    • @JamesMcNellis,是的,c ++ 03 中缺少该功能,其中擦除函数仅为序列返回下一个迭代器,而不是为关联容器返回下一个迭代器。对于必须在 C++03 中手动完成的关联容器
    • 您无需使用 begin 重新启动循环。而是在 erase() 调用中 POST-increment it++。起作用的原因可以认为是它的值被写下来供 erase() 使用,但是在实际调用擦除之前它是递增的,并且你删除了它指向的东西。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-23
      • 1970-01-01
      • 2012-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-22
      • 1970-01-01
      相关资源
      最近更新 更多