2015-09-26 86 views
0

我有一個像這樣的地圖for循環。這個地圖擦除是否安全?

std::map<int,std::string> mymap = {{1,"a"},{2,"b"},{3,"c"}}; 

for(std::map<int,std::string>::iterator it = mymap.begin(); it!=mymap.end(); ++it) 
{ 
    if(it->first==3) 
    { 
     mymap.erase(it); 
    } 
} 

std::cout << mymap.rbegin()->second << std::endl; 

如預期的那樣輸出爲「b」。問題是:這會導致無限循環(或崩潰)嗎?我的意思是

erase(it) 

這個迭代器它是無效的。如果擦除的項目不是最後一個,它應該是可以的,因爲在擦除之後「它」遞增,並且當評估條件時它指向最大值爲mymap.end()。但是,如果我擦除最後一個,擦除後mymap.end()應該在最後剩下的項目之後,然後它會增加。難道它不能以某種方式超出範圍?我不應該使用類似

for(std::map<int,std::string>::iterator it = mymap.begin(); it!=mymap.end(); ++it) 
{ 
    std::map<int,std::string>::const_iterator tempit = it; 
    const bool lastItemErased = ++tempit == mymap.end(); 

    if(it->first==3) 
    { 
     mymap.erase(it); 
    } 

    if(lastItemErased) break; 
} 

要安全嗎?

注意:如果我試圖用鍵3和2擦除元素,上述兩種運行和行爲都與預期相同。我不明白這是如何實現的,爲什麼它不會崩潰。我如何增加一個無效的迭代器?

更新:它必須使用c + + 03。我像這樣初始化了地圖,以便更容易地發佈問題。

+0

如果迭代器失效,那麼根據定義,使用它是不安全的。這是「未定義」的行爲,所以任何事情都可能發生。 – Galik

+0

爲了安全使用,請參考以下文檔中的示例:http://en.cppreference.com/w/cpp/container/map/erase – Galik

+0

擦除後使用rbegin將從地圖獲取最後一個元素,那麼爲什麼你認爲它應該崩潰?如果您使用的是前向迭代器,則必須按照鏈接中的答案指出的方式進行操作,以將問題標記爲重複的問題。 – Invictus

回答

1

編輯:只適用於C++ 11及以上。

std::map::erase返回一個新的有效迭代器對象(即在您的示例中爲mymap.end()後面的元素)。您應該使用該返回值:

for(std::map<int,std::string>::iterator it = mymap.begin(); it!=mymap.end();) 
{ 
    if(it->first==3) 
    { 
     it = mymap.erase(it); 
    } 
    else 
    { 
     ++it; 
    } 
} 

請參閱http://en.cppreference.com/w/cpp/container/map/erase以供參考。

+0

對不起。它必須與C++ 03一起工作。我像這樣初始化了地圖,以便更容易地發佈問題。 – TmsKtel

+1

@LukasW你的解決方案跳過一些迭代 –

+0

你說得對,@Galik&Piotr,我會糾正它。無論如何,新的C++ 03要求使這個答案無用。 –