Reputation: 1175
This question is very likely to be a duplicate, but I have not found anything on this issue.
Why can incrementing an iterator
placed at the last position in a vector
make it not equal to vector.end()
?
Or, in other words, why does this execute normally:
int main() {
vector<string> vec = {"ve"};
for (auto it = vec.begin(); it != vec.end(); it++) {}
return 0;
}
While this one goes into an infinite loop:
int main() {
vector<string> vec = {"ve"};
for (auto it = vec.begin(); it != vec.end(); it++) { it++; }
return 0;
}
And this one:
int main() {
vector<string> vec = {"ve"};
for (auto it = vec.begin(); it != vec.end(); it++) {
cout << (it == vec.end()) << " ";
cout << (*it == "ve") << endl;
it++;
}
return 0;
}
causes a SEGFAULT
having printed:
0 1
0
so, it
, in fact, was incremented, so that its contents became empty (optimised out, according to the debugger), but it did not become equal to vec.end()
. Why?
Upvotes: 3
Views: 1378
Reputation: 41168
You are checking for it != vec.end()
but with it++
happening twice you are skipping twice on each check. In other words you are running past the end of the vector
without spotting it.
If you add one more element to your vector then the loop will hit the end and stop as you will no longer skip the end point (obviously this is not a "proper" fix, it just demonstrates the problem).
To fix it check for end before the increment in the loop. You could also check using operator<
in the conditional but that's a little risky as you're leaving an invalid it
for a while which is bad for future maintenance of the code.
Upvotes: 4
Reputation: 54
In a for loop, the increment operation on the iterator is the last (and implicit) operation in a cycle.
Case 1: Loop begins with "it" = vec.begin(). Nothing happens. "it" is incremented (implicit). it = vc.end(). Loop ends. Hence the normal behavior.
Case 2: Loop begins with it = vec.begin(). "it" is incremented. it = vc.end(). "it" is incremented again (implicit). "it" moves to the next memory location, and keeps increasing in every cycle. Hence the infinite loop.
Case 3: Loop begins with it = vec.begin(). Check performed if it == vc.end(). Return false. Value in the memory location referenced by "it" is printed. "it" is incremented. it = vc.end(). "it" is incremented again (implicit). "it" moves to the next memory location, which is unallocated. Hence the SEG fault.
Upvotes: 1
Reputation: 15229
Imagine it
pointing to one before vec.end()
, supposedly the last iteration of the for
loop.
it != vec.end();
will be true
, so the loop will continue.it++;
in the body is executed. it == vec.end()
now.it++
from the for
loop head is executed. it
points one beyond vec.end()
.vec.end()
points one beyond the last element of vec
, which is still well-defined. vec.end() + 1
(the final value of it
) points two beyond the last element of vec
, which is undefined behavior.
That means that dereferencing the iterator accesses unallocated memory (explaining the segmentation fault). Undefined behavior again.
Upvotes: 5