Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have used the new range-based for loop provided by C++11 standard and I came up with the following question: suppose that we iterate over a vector<> using the range-based for, and we add some element in the end of the vector during this iteration. Thus, when do the loop end?

For instance, see this code:

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector<unsigned> test({1,2,3});
    for(auto &num : test) {
        cout << num << " ";
        if(num % 2)
            test.push_back(num + 10);
    }
    cout << "
";
    for(auto &num : test) 
        cout << num << " ";
    return 0;
}

I tested G++ 4.8 and Apple LLVM version 4.2 (clang++) with "-std=c++11" flag, and the output is (for both):

1 2 3
1 2 3 11 13

Note that the first loop terminates in the end of original vector, although we add other elements to it. It seems that the for-range loop evaluate the container end in beginning only. Is this, in fact, the correct behavior of range-for? Is it specified by the committee? Can we trust in this behavior?

Note that if we change the first loop by

for(vector<unsigned>::iterator it = test.begin(); it != test.end(); ++it)

with invalid the iterators and come up with a segmentation fault.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
428 views
Welcome To Ask or Share your Answers For Others

1 Answer

No you cannot rely on this behaviour. Modifying the vector inside the loop results in undefined behaviour because the iterators used by the loop are invalidated when the vector is modified.

The range based for loop

for ( range_declaration : range_expression) loop_statement

is essentially equivalent to

{
    auto && __range = range_expression ; 
    for (auto __begin = std::begin(__range),
        __end = std::end(__range); 
        __begin != __end; ++__begin) { 
            range_declaration = *__begin;
            loop_statement 
    }
}

When you modify the vector, the iterators __begin and __end are no longer valid and the dereferencing __begin results in undefined behaviour.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...