C++ 从C+中删除元素+;通过for循环映射

C++ 从C+中删除元素+;通过for循环映射,c++,map,stl,c++11,C++,Map,Stl,C++11,我的STL有点生锈,所以请原谅我问了一个可能很琐碎的问题。考虑下面的代码: map<int,int> m; ... for (auto itr = m.begin(); itr != m.end(); ++itr) { if (itr->second == 0) { m.erase(itr); } } map-m; ... 对于(自动itr=m.begin();itr!=m.end();++itr){ 如果(itr->秒==0){ m、 擦除(

我的STL有点生锈,所以请原谅我问了一个可能很琐碎的问题。考虑下面的代码:

map<int,int> m;
...
for (auto itr = m.begin(); itr != m.end(); ++itr) {
    if (itr->second == 0) {
        m.erase(itr);
    }
}
map-m;
...
对于(自动itr=m.begin();itr!=m.end();++itr){
如果(itr->秒==0){
m、 擦除(itr);
}
}

问题是:在地图上循环时删除元素安全吗

是的,但不是你做这件事的方式。擦除时将使itr无效,然后递增无效迭代器

auto itr = m.begin();
while (itr != m.end()) {
  if (itr->first == 0) {
    m.erase(itr++);
  } else {
    ++itr;
  }
}

我认为您根本不应该使用删除的迭代器——在列表的情况下,这会导致严重的问题,对于映射来说也不应该有所不同

编辑作者Matthieu M:此代码在C++0x中格式良好,允许作为MSVC的扩展

map<int,int> m;
...
auto itr = m.begin();
while (itr != m.end())
{
    if (itr->second == 0) {
        itr = m.erase(itr);
    }
    else 
    {
        itr++;
    }
}
map-m;
...
自动itr=m.begin();
while(itr!=m.end())
{
如果(itr->秒==0){
itr=m.erase(itr);
}
其他的
{
itr++;
}
}

对于给定的示例,使用以键为参数的擦除重载实际上更容易。此函数使用给定的键擦除贴图中的所有元素(对于贴图,此键始终为零或一个元素)

map-m;
// ...
m、 擦除(0);//删除键等于0的所有元素

再想一想,我可能应该使用类似于
remove\u if
的东西。然而,我仍然对这个问题的答案感兴趣。我不明白-为什么你需要一个循环来解决这个问题?映射只能包含一个值为0的键。因此,一个
查找
,如果找到了,那么该迭代器的
擦除
就可以了!尼姆,我的例子有点愚蠢。一个更好的例子是
如果(itr->second==0)
@Ben,啊-那就不一样了!;)@Ben:您不应该在排序范围上使用
remove\u,如果它通过重新排列元素违反了“排序”假设;m、 擦除(iter);itr=tmp;//这将是更容易理解的(依我看)。这也将是错误的,你正在增加之前,你删除。。。您是否打算,例如
auto tmp=itr++itr;m、 擦除(tmp)
?@Ben,@Erik:警告,对于基于节点的容器(
list
map
set
,…),标准中有两种
erase
方法,对于
erase
方法返回迭代器(如
vector
)的容器,使用此方法,
erase
行应为
itr=m.erase(itr)
。这个标志性的怪癖有效地打击了整个“互换性”的东西。。。因此在C++0x中进行了更正,因此所有未返回任何内容的
erase
现在都将迭代器返回到下一个元素:)根据我自己的理解,由于我经常使用此模式,您能否确认这意味着
m.erase(itr++)行可以变成
itr=m.erase(itr++)对于C++0x?@dlano中的所有容器,不会丢失
++
itr=m.erase(itr)应该是什么,参见标准C++映射::擦除不返回新的迭代器,这是MSVC扩展。这个代码格式不正确。没有返回迭代器的擦除函数版本。VisualC++标准库实现提供了这样的返回类型,但具体地指出它不符合C++。Standard@Xader:我还原了您的编辑并添加了免责声明,此代码在C++0x中格式良好,是删除容器中元素的规范方法,因此给出了最佳答案。(免责声明是为了让那些不理解
auto
意味着C++0x的人不会感到困惑)。反对者的标准参考:n3225 23.5.1.2元素访问。@Matthieu:我同意。由于OP在他的问题中写了“C++”,我假设auto只是在某种意义上被使用,“这种类型在C++03中写出来太长了,所以我将借用C++0x类型说明符auto,但是这个例子应该被认为是C++03”,或者类似的;)谢谢,我正在使用C++0x(正如auto关键字和C++0x标记所建议的那样),所以看起来是一个很好的解决方案。
map<int,int> m; 
// ...
m.erase(0); // erase all elements with key equivalent to 0