std::map<K, V> map_obj;
// calls needs_removing for each element and erases it, if true was returned
std::erase_if(map_obj, needs_removing);
// if you need to pass only part of the key/value pair
std::erase_if(map_obj, [] (auto& kv) { return needs_removing(kv.first); });
#ifdef __GXX_EXPERIMENTAL_CXX0X__
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 130. Associative erase should return an iterator.
/**
* @brief Erases an element from a %map.
* @param position An iterator pointing to the element to be erased.
* @return An iterator pointing to the element immediately following
* @a position prior to the element being erased. If no such
* element exists, end() is returned.
*
* This function erases an element, pointed to by the given
* iterator, from a %map. Note that this function only erases
* the element, and that if the element is itself a pointer,
* the pointed-to memory is not touched in any way. Managing
* the pointer is the user's responsibility.
*/
iterator
erase(iterator __position)
{ return _M_t.erase(__position); }
#else
/**
* @brief Erases an element from a %map.
* @param position An iterator pointing to the element to be erased.
*
* This function erases an element, pointed to by the given
* iterator, from a %map. Note that this function only erases
* the element, and that if the element is itself a pointer,
* the pointed-to memory is not touched in any way. Managing
* the pointer is the user's responsibility.
*/
void
erase(iterator __position)
{ _M_t.erase(__position); }
#endif
新旧样式示例:
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
typedef map<int, int> t_myMap;
typedef vector<t_myMap::key_type> t_myVec;
int main() {
cout << "main() ENTRY" << endl;
t_myMap mi;
mi.insert(t_myMap::value_type(1,1));
mi.insert(t_myMap::value_type(2,1));
mi.insert(t_myMap::value_type(3,1));
mi.insert(t_myMap::value_type(4,1));
mi.insert(t_myMap::value_type(5,1));
mi.insert(t_myMap::value_type(6,1));
cout << "Init" << endl;
for(t_myMap::const_iterator i = mi.begin(); i != mi.end(); i++)
cout << '\t' << i->first << '-' << i->second << endl;
t_myVec markedForDeath;
for (t_myMap::const_iterator it = mi.begin(); it != mi.end() ; it++)
if (it->first > 2 && it->first < 5)
markedForDeath.push_back(it->first);
for(size_t i = 0; i < markedForDeath.size(); i++)
// old erase, returns void...
mi.erase(markedForDeath[i]);
cout << "after old style erase of 3 & 4.." << endl;
for(t_myMap::const_iterator i = mi.begin(); i != mi.end(); i++)
cout << '\t' << i->first << '-' << i->second << endl;
for (auto it = mi.begin(); it != mi.end(); ) {
if (it->first == 5)
// new erase() that returns iter..
it = mi.erase(it);
else
++it;
}
cout << "after new style erase of 5" << endl;
// new cend/cbegin and lambda..
for_each(mi.cbegin(), mi.cend(), [](t_myMap::const_reference it){cout << '\t' << it.first << '-' << it.second << endl;});
return 0;
}
打印:
main() ENTRY
Init
1-1
2-1
3-1
4-1
5-1
6-1
after old style erase of 3 & 4..
1-1
2-1
5-1
6-1
after new style erase of 5
1-1
2-1
6-1
Process returned 0 (0x0) execution time : 0.021 s
Press any key to continue.
for (auto it = m.cbegin(); it != m.cend() /* not hoisted */; /* no increment */)
{
if (must_delete)
{
m.erase(it++); // or "it = m.erase(it)" since C++11
}
else
{
++it;
}
}
6条答案
按热度按时间rxztt3cl1#
C++20为
std::map
提供了std::erase_if
的便利重载。因此,您可以使用该函数以一行程序的形式执行此操作。
mklgxw1f2#
简而言之,“如何在迭代时从Map中删除?”
来自GCCMapimpl(注解GXX_EXPELENTAL_CXX0X):
新旧样式示例:
打印:
57hvy0tb3#
很悲伤,是吧?我通常的做法是构建一个迭代器容器,而不是在遍历过程中删除迭代器。然后循环遍历容器并使用map.erase()
wh6knrhe4#
标准的关联容器擦除习惯用法:
请注意,这里我们实际上需要一个普通的
for
循环,因为我们正在修改容器本身。基于范围的循环应该严格保留在我们只关心元素的情况下。RBFL的语法甚至不公开循环体中的容器,从而明确了这一点。**编辑。**C++11之前,不能擦除const-iterators。在那里你会说:
从容器中擦除元素与元素的一致性并不矛盾。通过类比,
delete p
一直是完全合法的,其中p
是指向常数的指针。恒定性不限制寿命; C++中的const值仍然可以停止存在。tquggr8v5#
我个人更喜欢这个模式,它稍微更清晰和简单,但代价是多了一个变量:
这种方法的优点:
it
和next_it
的含义在整个迭代过程中保持不变,允许您轻松添加引用它们的其他语句,而不必担心它们是否会按预期工作(当然,除了擦除后不能使用it
)。bybem2ql6#
假设是C++11,这里是一个一行循环体,如果这与你的编程风格一致的话:
还有一些小的风格变化:
Map::const_iterator
),而不是使用auto
。using
作为模板类型,使辅助类型(Map::const_iterator
)更易于读取/维护。