Eureka
Eureka

Reputation: 55

What is the difference between regular "for" statement and range-based "for" statement in C++

So, what is the difference between these two statement:

for(auto i : VectorName){}


for(auto i = VectorName.begin(); i != VectorName.end(); i++){}

For example, I have this program:

#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
 vector<char> vec = {'H','e','l','l','o','W','o','r','l','d','!'};
 for(auto i = vec.begin(); i != vec.end(); i++) // This loop has error
     {        
     cout << i << endl;
}
 for(auto k : vec) //This loop has no problem
 {
     cout << k << endl;
     }
     return 0;
}

I am confused because in this example in this Microsoft docs:

// cl /EHsc /nologo /W4
#include <deque>
using namespace std;

int main()
{
    deque<double> dqDoubleData(10, 0.1);

    for (auto iter = dqDoubleData.begin(); iter != dqDoubleData.end(); ++iter)
    { /* ... */ }

    // prefer range-for loops with the following information in mind
    // (this applies to any range-for with auto, not just deque)

    for (auto elem : dqDoubleData) // COPIES elements, not much better than the previous examples
    { /* ... */ }

    for (auto& elem : dqDoubleData) // observes and/or modifies elements IN-PLACE
    { /* ... */ }

    for (const auto& elem : dqDoubleData) // observes elements IN-PLACE
    { /* ... */ }
}

They noted that the range for statement is not better than the regular one.

Upvotes: 1

Views: 347

Answers (4)

Andreas DM
Andreas DM

Reputation: 10998

So, what is the difference between these two statement:

for(auto i : VectorName){}


for(auto i = VectorName.begin(); i != VectorName.end(); i++){}

The first one will iterate through every item in the collection; i is a copy of the item.

The second one gives you more control over the range; i is an iterator, dereference to access item.

Upvotes: 0

Stefan Riedel
Stefan Riedel

Reputation: 801

The difference in your case is, that the first version with iterators, well, uses iterators (that's why cout << i << endl; is not working), and the second version (the range-based for loop) gives you either a copy, a reference, or const reference.

So this:

for(auto i = vec.begin(); i != vec.end(); i++)
{
    cout << i << endl; // should be *i
}

uses iterators (vec.begin() gives you an iterator to the first element).

Whereas this:

for(auto i : vec)
{
    cout << i << endl;
}

uses copies of elements in your vector.

While this:

for(auto& i : vec)
{
    cout << i << endl;
}

uses references to your vector elements.

Upvotes: 3

Moberg
Moberg

Reputation: 5493

Regular for loop uses an explicit loop variable, in your examples an iterator i or iter (many times it is just an integer). To access elements in a vector for example, you need to use the loop variable to extract the elements from the vector.

Range-based for loops automatically gives you the elements inside the container you loop over, so there is no need to extract the elements inside the loop, you can immediately use k/elem.

About the comment you mention: that specific range-based style with no references is usually bad for performance (if the copy is unnecessary).

Upvotes: 0

Jarod42
Jarod42

Reputation: 217135

In

for (auto i = vec.begin(); i != vec.end(); i++)
{
    //cout << i << endl; // should be cout << *i << endl;
    auto& k = *i;
    cout << k << endl;
}

i is an iterator, you have to deference it to retrieve the value to be nearly equivalent to second snippet.

Upvotes: 0

Related Questions