考虑:
#include <map>
int main()
{
std::map< int, int > m;
m[ 0 ] = 0;
m[ 1 ] = 1;
m.erase( 0 ); // ok
m.erase( 2 ); // no-op
m.erase( m.find( 2 ) ); // boom!
}
(好吧,所以标题谈到擦除一个end()迭代器,但是find会返回一个不存在的键的end()。)
为什么删除不存在的键OK,但删除end()会爆炸。我在标准中没有看到任何明确的提及?
我在VS2005上尝试了这个(在调试配置中引发异常)和GCC 4.0.1(100%CPU)。它是依赖于实现的吗?
感谢。
答案 0 :(得分:32)
对于erase(key)
,标准说明删除了所有带有值键的元素。当然可能没有这样的价值观。
For erase(it)
(其中it
是std::map::iterator
),标准表示其所指向的元素已被删除 - 不幸的是,如果它是end()
则不会指向一个有效的元素,你在未定义的行为土地上,就像你使用end()
进行任何其他地图操作一样。有关详细信息,请参阅第23.1.2节。
答案 1 :(得分:18)
end()
不是地图的交互者。它实际上是“一个接一个结束”的地图。
'iterator'版本想要一个迭代器来映射地图。
擦除的“关键”版本执行查找并保护自己免受未找到的密钥的影响,迭代器版本假设您不打算破解内容。
答案 2 :(得分:3)
而不是上一篇文章中给出的例子......
MapType::iterator it = the_map.find ("new_key");
// Does not exist.
if (it == the_map.end()) {
the_map.insert (std::make_pair ("new_key", 10));
}
进行两次树遍历,使用...
pair<MapType::iterator, bool> rc = the_map.insert(make_pair("new_key", 0));
if (rc.second)
rc.first.second = 10;
这样你就可以进行一次树遍历,并且你可以使用迭代器来为其他东西滚动。
答案 3 :(得分:1)
这是一个快速示例,说明在删除时如何使用带有迭代器的STL映射。执行插入时我也会做同样的事情。我个人喜欢使用typedef来专门定义地图,但选择权在你手中。
typedef std::map... MapType;
MapType the_map;
MapType::iterator it = the_map.find ("key");
if (it != the_map.end()) {
// Do something productive.
the_map.erase (it);
}
MapType::iterator it = the_map.find ("new_key");
// Does not exist.
if (it == the_map.end()) {
the_map.insert (std::make_pair ("new_key", 10));
}
希望这有帮助!