首頁 > 後端開發 > C++ > 主體

如何在使用基於範圍的 For 循環迭代期間安全地刪除 std::vector 中的元素?

Susan Sarandon
發布: 2024-11-03 17:09:03
原創
852 人瀏覽過

How to Safely Erase Elements from a std::vector During Iteration with a Range-Based For Loop?

使用基於範圍的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(N

2) 降低到 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&amp; 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中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!