如何使用迭代器删除std :: map元素? [英] How can I delete elements of a std::map with an iterator?

查看:131
本文介绍了如何使用迭代器删除std :: map元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想循环执行 std :: map ,并根据其内容删除项目。如何最好地完成?

I would like to loop through an std::map and delete items based on their contents. How best would this be done?

推荐答案

如果你有一个符合C ++ 11的编译器,这里有一个简单的方法这个:

If you have a C++11-compliant compiler, here's an easy way to do this:

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

这个想法是从一开始就将迭代器向前走的容器到最后,检查每个步骤是否应删除当前的键/值对。如果是这样,我们使用擦除成员函数删除迭代的元素,然后它将迭代器返回给地图中的下一个元素。否则,我们推进迭代器正常转发。

The idea is to walk the iterator forward from the start of the container to the end, checking at each step whether the current key/value pair should be deleted. If so, we remove the element iterated over using the erase member function, which then returns an iterator to the next element in the map. Otherwise, we advance the iterator forward normally.

如果您没有符合C ++ 11的编译器,或者您正在使用较旧的代码库,则有点棘手在C ++ 11之前, erase 成员函数不会将迭代器返回给地图中的下一个元素。这意味着为了在迭代时删除元素,您需要使用三部分舞蹈:

If you do not have a C++11-compliant compiler, or you're working with an older codebase, things are a bit trickier. Before C++11, the erase member function would not return an iterator to the next element in the map. This meant that in order to remove an element while iterating, you'd need to use a three-part dance:


  1. 复制当前的迭代器。

  2. 将当前迭代器提前到下一个元素。

  3. 在副本上调用擦除的旧迭代器。

  1. Copy the current iterator.
  2. Advance the current iterator to the next element.
  3. Call erase on the copy of the old iterator.

这里显示:

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 在迭代器上,你会使无效,这意味着像递增和递减这样的操作会导致未定义的行为。上述代码通过设置迭代器的副本来实现,推进 itr ,使其位于下一个元素,然后擦除迭代器的临时副本。

This process was required because if you just called erase on the iterator, you'd invalidate it, meaning that operations like increment and decrement would lead to undefined behavior. The above code gets around this by setting up a copy of the iterator, advancing itr so that it's at the next element, then erasing the temporary copy of the iterator.

使用一些聪明的诡计,可以以可读性为代价缩小代码。以下模式在较旧的C ++代码中很常见,但在C ++ 11中不是必需的:

Using some Clever Trickiness, it's possible to shrink this code down at the expense of readability. The following pattern is common in older C++ code, but isn't necessary in 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;
    }
}

这里使用后增量运算符是复制旧的迭代器的聪明方式(请记住postfix ++操作符返回原始迭代器值的副本),同时也推进旧的迭代器。

The use of the post-increment operator here is a clever way of making a copy of the old iterator (remember that a postfix ++ operator returns a copy of the original iterator value) while also advancing the older iterator.

这篇关于如何使用迭代器删除std :: map元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆