簡體   English   中英

在 C++ stl map 中遍歷時擦除給出運行時錯誤

[英]Erasing while traversing in C++ stl map giving runtime error

以下 C++ 代碼行給出運行時錯誤,但如果刪除操作mymap.erase(v)則它可以工作:

map<int,int> mymap = {{1,0},{2,1},{9,2},{10,3},{11,4}};
for(auto it=mymap.rbegin();it!=mymap.rend();){
    int v=it->first;
    ++it;
    mymap.erase(v);
}

演示

這里的迭代器在刪除it的值v之前被改變了,所以我相信迭代器it應該保持不受影響。

當您調用erase(v)時,您正在使下一個reverse_iterator (來自++it )正在使用的基本iterator無效。 因此,您需要從擦除值之前的基本iterator創建一個新的reverse_iterator

此外,與其刪除reverse_iterator所指的,不如刪除基本iterator ,因為您已經知道要刪除哪個元素。 無需再次使map go 尋找該值。

這對我有用:

map<int,int> mymap = {{1,0},{2,1},{9,2},{10,3},{11,4}};
for(auto it = mymap.rbegin(); it != mymap.rend(); ){
    auto v = --(it.base());
    v = mymap.erase(v);
    it = map<int,int>::reverse_iterator(v);
}

演示

另一方面,這個循環本質上只是從mymaperase()所有元素,因此更好的選擇是使用mymap.clear()代替。

事實上, std::map::erase

對已擦除元素的引用和迭代器無效。 其他引用和迭代器不受影響。

但是std::reverse_iterator

對於從迭代器 i 構造的反向迭代器 r,關系&*r == &*(i-1)始終為真(只要 r 是可取消引用的); 因此,從一個過去的迭代器構造的反向迭代器取消對序列中最后一個元素的引用。

當您查看 cppreference 頁面上的圖像時,可能會更清楚。

圖片

關鍵部分是“反向迭代器將迭代器存儲到下一個元素而不是它實際引用的元素”。

結果(對您的代碼的小修改)

auto& element = *it;       // fails in the next iteration, because...
int v = element.first;
++it;                      // now it stores an iterator to element
mymap.erase(v);            // iterators to element are invalidated 

您正在擦除it在下一次迭代中使用的元素。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM