Consider the following code:
unordered_set<T> S = ...;
for (const auto& x : S)
if (...)
S.insert(...);
This is broken correct? If we insert something into S then the iterators may be invalidated (due to a rehash), which will break the range-for because under the hood it is using S.begin ... S.end.
Is there some pattern to deal with this?
One way is:
unordered_set<T> S = ...;
vector<T> S2;
for (const auto& x : S)
if (...)
S2.emplace_back(...);
for (auto& x : S2)
S.insert(move(x));
This seems clunky. Is there a better way I'm missing?
(Specifically if I was using a hand-rolled hash table and I could block it from rehashing until the end of the loop, it would be safe to use the first version.)
Update:
From http://en.cppreference.com/w/cpp/container/unordered_map/insert
If rehashing occurs due to the insertion, all iterators are invalidated. Otherwise iterators are not affected. References are not invalidated. Rehashing occurs only if the new number of elements is higher than
max_load_factor() * bucket_count()
.
Could you mess with max_load_factor
somehow to prevent rehashing?