【问题标题】:iterator invalidation in map C++地图 C++ 中的迭代器失效
【发布时间】:2018-04-18 09:02:19
【问题描述】:

我有一个示例程序,我试图在其中查看迭代器在从地图中删除元素时如何失效。

程序在这里:

#include <iostream>
#include <map>

using namespace std;

int main(int argc, char *argv[])
{

    map<int, int> myMap;

    myMap.insert(pair<int, int>(0, 2));    
    myMap.insert(pair<int, int>(1, 4));    
    myMap.insert(pair<int, int>(3, 18));    
    myMap.insert(pair<int, int>(2, 20));    

    map<int, int>::iterator it; 

    for(it = myMap.begin(); it != myMap.end(); ++it) 
    {   
        myMap.erase(it);  // erasing the element pointed at by iterator

        cout << it->first << endl; // iterator is invalid here 
    }   
    return 0;
}

问题是我得到的输出是:

0
1
2
3  

为什么迭代器没有失效并给我错误的结果。任何帮助将不胜感激。

C++ STL 映射的文档说:引用和迭代器 擦除的元素无效。其他引用和迭代器 不受影响。

【问题讨论】:

  • 您在问为什么有时使用无效的迭代器有效?这有点像在问为什么人们在不带降落伞的情况下有时能活下来
  • 您的迭代器已失效。您正在观察未定义行为的影响。
  • 取消引用无效的迭代器是未定义的行为。它可以做任何事情,包括返回(看似)正确的值。
  • 那么,你是说它确实无效?
  • 是的,您正在调用未定义的行为。

标签: c++ stl


【解决方案1】:

使用无效的迭代器是未定义的行为。在这种情况下,任何事情都可能发生。

为什么您会看到这些值?迭代器包含一个指向某块内存的指针,纯属意外,该内存尚未归还给系统,也尚未被覆盖。这就是为什么您仍然可以看到已经“死”的值。

它不会改变任何东西,它仍然是未定义的行为,并且下次运行程序时,映射元素所在的内存页面可能已经再次返回给操作系统,并且您会遇到访问冲突(分段错误) ...

【讨论】:

    【解决方案2】:

    无效的迭代器并不意味着它的内部数据被擦除了。有时就像在这种情况下,无效的迭代器可能持有对下一项的有效引用。但是,像这样使用它是未定义的行为,它可能会在您的应用程序中导致一些问题。

    【讨论】:

      【解决方案3】:

      默认情况下不对无效迭代器进行运行时检查。

      您可以使用-D_GLIBCXX_DEBUG 为 GNU C++ 标准库启用对无效迭代器的调试检查。这会产生以下运行时错误:

      iterator "this" @ 0x0x7fff9f3d7060 {
      type = N11__gnu_debug14_Safe_iteratorISt17_Rb_tree_iteratorISt4pairIKiiEENSt7__debug3mapIiiSt4lessIiESaIS4_EEEEE (mutable iterator);
        state = singular;
        references sequence with type `NSt7__debug3mapIiiSt4lessIiESaISt4pairIKiiEEEE' @ 0x0x7fff9f3d7150
      }
      

      对于其他标准库,请查看文档。

      【讨论】:

      • 请注意,这是在 UB 的范围内工作的:标准说“任何事情都可能发生”,然后实现说“抛出异常符合任何事情”
      • @Caleth 遵循这个极端的逻辑,即使没有调试迭代器,它也可以打印此消息,但它很少发生,以至于尚未观察到。学究起来,标准不要求发生 UB 时有任何特定的行为,这与“任何事情都可能发生”完全不同。
      • “不要求任何特定行为”是的,但也“不禁止任何特定行为”。换句话说,“任何事情都可能发生”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-06
      • 2017-10-05
      • 2023-01-13
      • 1970-01-01
      相关资源
      最近更新 更多