I want to modify (push_back) element while iterate vector like this:
auto main() -> int {
std::vector<double> v { 1, 2, 3 };
for (auto& num : v) {
std::cout << num << "\n";
v.push_back(num);
}
std::cout << "===========\n";
for (const auto& num : v) {
std::cout << num << "\n";
}
}
The output is:
1
1.00938e-320
0
===========
1
2
3
1
1.00938e-320
0
Why the output is not something like this:
1
2
3
===========
1
2
3
1
2
3
If range based for is just sugar of:
for (auto& it{v.begin()}, it != v.end(), it++)
Shouldn’t there be two possible situations here?
-
v.end()evalued every iterate and never end. It should be an infinite loop. -
v.end()evalued one time before iterate and should output as I expected:
1
2
3
===========
1
2
3
1
2
3
>Solution :
As you can see when you call std::vector::push_back:
If after the operation the new size() is greater than old capacity() a
reallocation takes place, in which case all iterators (including the
end() iterator) and all references to the elements are invalidated.
Otherwise only the end() iterator is invalidated.
(emphasis is mine)
Range-based loop is only a syntactic sugar for using the iterators (and specifically compare to the end() iterator after each iteration).
Therefore calling push_back inside it invokes undefined-behavior.
This means the standard gives no guarantee for the output of the program. Any output you observe is legitimate.