1. 程式人生 > >c++ STL容器在迴圈中刪除迭代器的處理細節

c++ STL容器在迴圈中刪除迭代器的處理細節

c++中STL容器vector/list/map/set/deque/string等刪除元素的問題,迭代器容易出現以下錯誤,示例程式碼如下:
std::vector<int> arrayList;
...
std::vector<int>::iterator it = arrayList.begin();
for ( ; it != arrayList.end(); it++)
{
    if (...)
        arrayList.erase(it);
}
顯然若條件為真即if(...)為true,那麼程式執行除錯就會崩潰。
根本原因是:當容器中的一個元素被刪除時,指向該元素後續的迭代器變得無效。上面的程式碼中,只要執行了erase(it),那麼it就會變得無效,那麼執行it++就肯定會出錯。

通常有兩條規則:
1. 對於節點式容器(map, list, set)元素的刪除,插入操作會導致指向該元素的迭代器失效,其他元素迭代器不受影響
2. 對於順序式容器(vector,string,deque)元素的刪除、插入操作會導致指向該元素以及後面的元素的迭代器失效

供參考的正確的寫法如下:
1.對於節點式容器(map/list/set)
std::map<int, struct> mapInfo;
...
std::map<int, struct>::iterator it = mapInfo.begin();
while (it != mapInfo.end())
{
    if (...)
    {
        // 刪除節點的前,對迭代器進行後移的操作,因為其他元素不會失效
        mapInfo.erase(it++);
    }
    else
    {
        it++;
    }
}
2.對於順序式容器(vector/string/deque)
std::vector<int> arrayInt;
...
std::vector<int>::iterator it = arrayInt.begin();
while (it != arrayInt.end())
{
    if (...)
    {
        // 需要注意的是,因為順序式容器會使本身和後面的元素迭代器都失效,所以不能簡單的++操作
        // 順序式容器的erase()會返回緊隨被刪除元素的下一個元素的有效迭代器(節點式容器的erase()的返回值是void)
        it = arrayInt.erase(it);
    }
    else
    {
        it++;
    }
}
補充說明:容器看具體STL庫的實現了, VS中兩類容器的earse都返回下一個迭代器指標