Quick A: Once a value is deleted, iterators pointing to it become invalid.
Recently on SO:
unordered_map element being deleted
After you call
my_umap.erase(...)
, your iterator becomes invalid:cppreference.com says:
References and iterators to the erased elements are invalidated. Other iterators and references are not invalidated.This means that once the item is erased, the iterators that pointed to it are no longer valid.You've got a couple of options:
1. Use the iterator to erase, and use the return value of
erase()
Since C++11, erasing by iterator will return an iterator pointing to the next item in the map. So you can use this to keep your iterator valid:
auto it = my_umap.begin(); while (it != my_umap.end()) { MyStruct& myStruct = it->second; const bool deleteEntry = myStruct.ts.IsElapsed(std::chrono::seconds(5)); if(deleteEntry){ assert(my_umap.size() >= 1); it = my_umap.erase(it); // <-- Return value should be a valid iterator. } else{ ++it; // Have to manually increment. } }2. Store your iterators in a list object and erase after iteration.
Alternatively, you can store delete candidates in a list object (e.g. vector and delete them after your initial iteration:
std::vector<MapType::iterator> deleteCandidates; for(auto it = my_umap.begin(); it != my_umap.end(); ++it){ MyStruct& myStruct = it->second; const bool deleteEntry = myStruct.ts.IsElapsed(std::chrono::seconds(5)); if(deleteEntry) deleteCandidates.push_back(it); } for (auto it : deleteCandidates) { my_umap.erase(it); }As for why your assertion is failing, you're probably encountering undefined behaviour by accessing an invalid iterator, making your
for
loop believe that the map is still not empty (becauseinvalidIterator != my_umap.end()
).
Add a Comment
Comments are closed.