与C ++中擦除映射迭代器的行为不一致

时间:2013-11-19 20:14:42

标签: c++ map iterator erase

我对地图的擦除功能的行为感到很困惑。在下面的简单示例中,代码输出“224”。但是,如果您注释掉“m ['e'] = 5”行,则输出“221”。这两个结果对我都没有意义。有人可以解释这里的逻辑吗?

#include <iostream>
#include <map>
using namespace std;

int main(){

        map<char, int> m;
        m['a'] = 1;
        m['b'] = 2;
        m['c'] = 3;
        m['d'] = 4;
        m['e'] = 5;

        map<char, int>::iterator it = m.begin();        it++; 
        cout << it->second;                             
        m.erase(it); 
        cout << it->second;
        it++;
        cout << it->second << endl;
}

3 个答案:

答案 0 :(得分:3)

擦除后无法使用迭代器。它无效且行为未确定(崩溃,故障值?):

http://en.cppreference.com/w/cpp/container/map/erase

答案 1 :(得分:0)

map<char, int>::iterator it = m.begin();        it++; 
cout << it->second;                             
m.erase(it);  // (1) 
cout << it->second; // (2)
it++; // (3)
cout << it->second << endl;

您已在位置(1)处使迭代器无效,因此尝试在(2)(3)中取消引用它是未定义的行为。它实际上与删除指针然后尝试取消引用它相同。

答案 2 :(得分:0)

要删除pre c ++ 11中地图中的元素,您可以使用以下模式:

for( map_type::iterator it = map.begin(); it != map.end(); ) {
   if( condition_to_erease ) map.erase( it++ );
   else ++i;
}

为什么map.erase( it++ );有效?因为它基本上等同于这段代码:

map::iterator tmp = it;
++it;
map.erase( tmp );

如果你想有效地使用C ++,你应该理解postfics / prefics运算符的语义。

对于c ++ 11,你也可以使用它:

for( auto it = map.begin(); it != map.end(); ) {
   if( condition_to_erease ) it = map.erase( it );
   else ++i;
}

我认为在Visual C ++ std::map::erase()中也返回了迭代器,但这不符合标准。