1. 程式人生 > >C++:在迭代中刪除map的成員

C++:在迭代中刪除map的成員


首先要清楚一點,迭代器相當於是容器上的指標,容器可以自己管理記憶體,因此迭代器可能失效。
如果你在不知情的情況下使用了失效的迭代器,後果是不可預料的。可能程式立即崩掉,也可能什麼事都沒有發生。崩掉了算你幸運,因為你至少知道出了問題,不然有你受的。

回到正題,我想說什麼呢?
比如:
程式程式碼 程式程式碼
map<string,int> theMap;
// add somethingto theMap...

for(auto iter1 = theMap.begin(); iter1 !=theMap.end(); ++iter1)
{
    if(iter1->second == xxx)
   {
        theMap.erase(iter1);  //#1erase the element ??!!
   }
}


看樣子貌似非常正常的一段程式碼。在一個map中尋找值為xxx的項並刪除。
但是實際上這個程式碼是完全錯誤的,會導致無法預料的結果。

問題就在#1處。一旦你erase了一個iterator指向的內容,這個iterator就無效了。
這時候你再對這個iterator做任何操作其結果都是未定義的。

那麼該怎麼辦呢?
還好,對於map這種以指標構建起來的容器來說,可以保證一個元素刪除了,不影響指向其它元素的迭代器。
因此就可以這樣做(《C++Standard Library》上建議的正確做法):
程式程式碼
程式程式碼
for(auto iter1 = theMap.begin(); iter1 !=theMap.end(); )
{
    if(iter1->second == xxx)
   {
        theMap.erase(iter1++);  //#1
   }else
   {
        ++iter1;
   }
}

這個遍歷把迭代器的自增從for頭部中取出,丟到迴圈體中去。#1處,iter1++這個運算先自增,但是卻返回了自增前的迭代器的一個臨時拷貝。然後這個臨時迭代器指向的內容被刪除了,但是iter1本身已經自增到下一個位置了,不受影響。