Iterator invalidation:
rehash | Always
I'm trying to invalidate a iterator. But it stay valid even after a manual call rehash()
.
Test sample:
std::unordered_set<int> set;
set.insert(10);
auto it = set.begin();
const int& ref = *it;
for(int i = 0; i < 10; i) {
set.insert(i);
std::cout << *it << " | " << ref << " : " << set.load_factor() << " / " << set.max_load_factor() << std::endl;
}
set.rehash(100);
std::cout << *it << " | " << ref << " : " << set.load_factor() << " / " << set.max_load_factor() << std::endl;
stdout:
10 | 10 : 1 / 1
(rehash)
10 | 10 : 0.6 / 1
10 | 10 : 0.8 / 1
10 | 10 : 1 / 1
(rehash)
10 | 10 : 0.545455 / 1
10 | 10 : 0.636364 / 1
10 | 10 : 0.727273 / 1
10 | 10 : 0.818182 / 1
10 | 10 : 0.909091 / 1
10 | 10 : 1 / 1
10 | 10 : 0.108911 / 1
CodePudding user response:
I'm trying to invalidate a iterator.
Calling rehash
does invalidate iterators.
But it stay valid even after a manual call rehash().
Not it does not stay valid.
What you do not spell out explicitly is: You get expected output hence conclude that the iterator is still valid.
You cannot test if an iterator is valid. Dereferencing an invalid iterator is undefined. The result can be anything (including a seemingly correct result). Colloquially speaking, "invalid" means "no guarantee that it works", it does not mean "guaranteed to fail". This is the case in general with undefined behavior. You cannot conclude from correct looking output that the code is correct.
A somewhat silly but imho somewhat useful analogy is a broken calculator. It has *
and
swapped. You ask for the result of 2 2
and get 4
. Looks correct, but from that you cannot conclude that the calculator is not broken.