c++ - 如何使用迭代器删除 std::map 的元素?

标签 c++ map iterator stdmap

我想遍历 std::map 并根据其内容删除项目。如何做到最好?

最佳答案

如果您有兼容 C++11 的编译器,这里有一个简单的方法:

std::map<K, V>::iterator itr = myMap.begin();
while (itr != myMap.end()) {
    if (ShouldDelete(*itr)) {
       itr = myMap.erase(itr);
    } else {
       ++itr;
    }
}

这个想法是让迭代器从容器的开始向前移动到结束,在每一步检查当前的键/值对是否应该被删除。如果是这样,我们使用 erase 成员函数删除迭代过的元素,然后返回映射中下一个元素的迭代器。否则,我们将迭代器正常向前推进。

如果您没有兼容 C++11 的编译器,或者您使用的是较旧的代码库,那么事情就有点棘手了。在 C++11 之前,erase 成员函数不会返回指向映射中下一个元素的迭代器。这意味着为了在迭代时移除元素,您需要使用三部分舞蹈:

  1. 复制当前迭代器。
  2. 将当前迭代器推进到下一个元素。
  3. 在旧迭代器的拷贝上调用 erase

这里显示:

std::map<K, V>::iterator itr = myMap.begin();
while (itr != myMap.end()) {
    if (ShouldDelete(*itr)) {
       std::map<K, V>::iterator toErase = itr;
       ++itr;
       myMap.erase(toErase);
    } else {
       ++itr;
    }
}

这个过程是必需的,因为如果你只是在迭代器上调用 erase,你会 invalidate 它,这意味着像递增和递减这样的操作会导致未定义的行为。上面的代码通过设置迭代器的拷贝来解决这个问题,推进 itr 使其位于下一个元素,然后删除迭代器的临时拷贝。

使用一些巧妙的技巧,可以以牺牲可读性为代价缩小此代码。以下模式在较旧的 C++ 代码中很常见,但在 C++11 中不是必需的:

std::map<K, V>::iterator itr = myMap.begin();
while (itr != myMap.end()) {
    if (ShouldDelete(*itr)) {
       myMap.erase(itr++);  // <--- Note the post-increment!
    } else {
       ++itr;
    }
}

这里使用后自增运算符是制作旧迭代器拷贝的一种巧妙方法(请记住,后缀++ 运算符返回原始迭代器值的拷贝),同时也推进旧迭代器。

关于c++ - 如何使用迭代器删除 std::map 的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4600567/

相关文章:

c++ - 将 org-mode 表数据传递到 org-mode C++ 源代码块

c++ - 如何按插入顺序从 map 中检索元素?

c++ - std::map emplace/insert 正在插入的移动值

c++ - 在 'insert' 之后重新使用迭代器进入 vector

c++ - 从一对迭代器 C++ 创建 STL vector

C++ 调试断言失败 _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

c++ - 使用 std::tm 作为 std::map 中的键

c++ - 如何使用静态STL列表的迭代器?

graph - D语言中的并行迭代器

c++ - MFC 应用程序 : animating graphics cause program to not respond