问题描述
我想遍历 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;
}
}
这个想法是让迭代器从容器的开始向前移动到结束,在每一步检查当前的键/值对是否应该被删除.如果是这样,我们使用 erase
成员函数删除迭代过的元素,然后返回映射中下一个元素的迭代器.否则,我们将迭代器正常向前推进.
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:
- 复制当前迭代器.
- 将当前迭代器推进到下一个元素.
- 在旧迭代器的副本上调用
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
使其位于下一个元素,然后擦除迭代器的临时副本.
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;
}
}
这里使用后自增运算符是制作旧迭代器副本的一种巧妙方法(请记住,后缀 ++ 运算符返回原始迭代器值的副本)同时也推进旧迭代器.
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 的元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!