2014-04-29 20 views
-1

我正在使用Xcode和C++ 11作爲std :: map。我的地圖中的一些元素有一個標誌,說他們需要刪除。是否std :: map :: erase(it ++)維護一個有效的迭代器指向地圖中的下一個元素?

我想循環遍歷地圖,在O(n)時間擦除標記的元素。擦除調用不會返回迭代器。我已經看到了某種擦除(it ++)實現,但是我沒有證據表明這種調用可以工作,因爲在擦除操作之後但在增量操作之前迭代器將變爲無效。

我目前的代碼似乎效率很低。

for(auto it = myMap.begin(); it != myMap.end(); ++it) 
{ 
    delete *it; 
    myMap.erase(it); 
    it = myMap.begin(); //how can I avoid iterating through the map again 
} 
+0

使用'的unique_ptr <>'來管理對象的生命週期,然後使用'擦除/ remove_if'與檢查你移開標記的λ。以http://en.cppreference.com/w/cpp/algorithm/remove爲例。 – mythagel

回答

3

從在線文檔:

「迭代器,指針和引用該函數刪除元素的引用是無效的。所有其他迭代器,指針和引用保持其有效性。」

所以,也許這樣的:

for(auto it = myMap.begin(); it != myMap.end();) 
{ 
    auto itPrev = it; 
    ++it; 

    if(shouldBeDeleted(*itPrev)) 
     myMap.erase(itPrev); 
} 

編輯:你提到的erase(it++)想法實際上是好的,因爲增量發生(並返回舊,預增量值的副本)erase()被調用之前。它實際上相當於:

template<typename IteratorT> 
IteratorT PostIncrement(IteratorT& it) 
{ 
    auto copy = it; 
    ++it; 
    return copy; 
} 

for(auto it = myMap.begin(); it != myMap.end();) 
    myMap.erase(PostIncrement(it)); 

它與另一個例子的數量相同。順便說一句,這就是爲什麼你應該正常使用前綴++與迭代器;該複製操作是額外的開銷,並且你通常不需要它。

+0

你指的是哪些在線文檔? – Gandalf458

+0

我看到的是這裏:http://www.cplusplus.com/reference/map/map/erase/。該頁面還表示C++ 11應該有'erase'重載,它們會返回'iterator's,但也許它們不在您使用的實現中。 – dlf

+0

好的,我沒有注意到我可以點擊的C++ 11選項卡。這似乎是有道理的,如果沒有錯誤,我會將其標記爲正確。 – Gandalf458

3

std::map::erase()被傳遞一個迭代器時,它會將一個迭代器返回到被擦除元素之後的下一個元素。這使您可以在不重新開始的情況下繼續進行迭代。

嘗試這種情況:

auto it = myMap.begin(); 
while (it != myMap.end()) 
{ 
    if (it->flagged) 
    { 
     delete *it; 
     it = myMap.erase(it); 
    } 
    else 
     ++it; 
} 
+0

對於Xcode的C++ 11標準實現來說,這是不正確的。 – Gandalf458

相關問題