使用基於範圍的For 循環迭代時從std::vector 中刪除元素
迭代std::vector 並刪除匹配特定條件的元素可能是程式設計中的常見任務。然而,標準的基於範圍的 for 迴圈語法提出了挑戰,因為在迭代時嘗試擦除元素可能會使迭代器無效。
在基於範圍的For 循環內擦除的問題
以下程式碼片段演示了該問題:
for(iterator it = begin; it != end; ++it) { if(it->somecondition() ) { erase it } }
雖然目的是刪除了該問題:
雖然目的刪除滿足條件的元素,但這種方法是不正確的。當一個元素被刪除時,迭代器就變得無效。繼續使用該迭代器進行迭代會導致未定義的行為。
解決方案1:使用常規For 循環和明確迭代器操作
for(iterator it = begin; it != end(container) /* !!! */;) { if (it->somecondition()) { it = vec.erase(it); // Returns the new iterator to continue from. } else { ++it; } }
一個解決方案是使用常規for 循環使用明確迭代器操作:
請注意這裡的關鍵差異:我們在每次迭代上明確呼叫end(container) 以獲得新的結束迭代器。這是必要的,因為擦除元素會使原始迭代器失效。
解決方案2:使用std::remove_if 和擦除
iterator it = std::remove_if(begin, end, pred); vec.erase(it, vec.end());
更有效的替代方案是組合std:: remove_if和erase():
std::remove_if刪除與指定謂詞相符的元素,而erase()刪除它們。此方法將第一個解中的時間複雜度從 O(N2) 降低到 O(N)。
特定於所提供範例的解決方案
class remove_by_caller { public: remove_by_caller(AguiWidgetBase* pWidget) : mWidget(pWidget) {} template <typename T> // for now a template bool operator()(const T& pX) const { return pX.getCaller() == mWidget; } private: AguiWidgetBase* mWidget; }; std::vector<AguiTimedEvent>::iterator it = std::remove_if(timedEvents.begin(), timedEvents.end(), remove_by_caller(widget)); timedEvents.erase(it, timedEvents.end());
以上是如何在使用基於範圍的 For 循環迭代期間安全地刪除 std::vector 中的元素?的詳細內容。更多資訊請關注PHP中文網其他相關文章!