I am confused as to what what the difference is between for loop and for each loop in C++. I read tutorials and some books but I am yet to see how for each loop is different. With arrays, examples I have seen seem to suggest for each loop loops through the whole elements at a go. Could that be the special advantage range based loop has?
-
1Please update your question with specific code samples and highlight the differences that you see.quamrana– quamrana2019-11-19 11:36:05 +00:00Commented Nov 19, 2019 at 11:36
-
1Basically, range-based loops are faster to be typed (with less characters), while ordinary for loops are more generic.Daniel Langr– Daniel Langr2019-11-19 11:40:53 +00:00Commented Nov 19, 2019 at 11:40
-
1Ordinary loops perform init/condition/effect, whereas foreach loops work directly with iterators. You can model one in the other, but that doesn't make them equivalents.Qix - MONICA WAS MISTREATED– Qix - MONICA WAS MISTREATED2019-11-19 11:48:44 +00:00Commented Nov 19, 2019 at 11:48
-
2"I read tutorials and some books" - Can you tell us what about those tutorials confused you? Otherwise any answer we give will likely just cause the same confusion.Galik– Galik2019-11-19 12:12:25 +00:00Commented Nov 19, 2019 at 12:12
-
1@Qix I would expect that as the answers. That is not the opinion, that is the fact. All of the answers available now do have an opinion based approach in them.Croolman– Croolman2019-11-19 12:15:48 +00:00Commented Nov 19, 2019 at 12:15
2 Answers
The main difference is that the ordinary for-loop uses an additional variable used as an index inside the array and has the scope of the loop and you can yourself write the condition of the for loop.
For example let's assume that you need to output either all even elements of an array or until an element with a zero value is encountered. You can write
#include <iostream>
int main()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 11, 12 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N && a[i] != 0; i++ )
{
if ( a[i] % 2 == 0 ) std::cout << i << ": " << a[i] << '\n';
}
return 0;
}
The program output is
1: 2
3: 4
5: 6
7: 8
How to do this with the range-based for loop? For starters before the loop you need to declare a variable that will play the role of the index. One drawback of this is the variable is not declared in the scope where it is used.
Also to stop the iterations of the loop you need to use a break statement within the loop. That also makes the code more complicated.
Compare the above program with this
#include <iostream>
int main()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 11, 12 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t i = 0;
for ( const auto &item : a )
{
if ( item == 0 )
{
break;
}
else if ( item % 2 == 0 )
{
std::cout << i << ": " << item << '\n';
}
++i;
}
return 0;
}
In general to use the range based for loop the used container either shall have member functions begin and end or the general functions begin and end shall support the container. For arrays begin and end mean expressions a and a + N.
3 Comments
The difference between a for loop and a range based for loop is roughly analogous to the difference between goto and a for loop. Former is a more generic control flow, while the latter is more structured. Every range based loop can be written as a for loop and every for loop can be written as a goto. But the reverse is not true.
Goto encapsulates the idea of jumping elsewhere. Loop encapsulates the idea of repetition (which involves jumping back). Range based loop encapsulates the idea of iterating over a range from begin until end (which involves repetition).
If your intention is to iterate over an entire range, then the range based loop is typically syntactically simpler, and easier to understand than a for loop. Likewise, a for loop is easier to understand than a goto loop. This is what makes structured approach superior. Compare for example the following, and consider which one is easier to understand:
for (auto it = list.begin(), end = list.end(); it != end; ++it) {
auto& element = *it;
// do stuff with element
}
for (auto& element : list) {
// do stuff with element
}
loops through the whole elements at a go. Could that be the special advantage range based loop has?
Looping through an entire range is what range based loop can do. A for loop can do that too. But a for loop can do much more: it can iterate indices, it can iterate indefinitely, it can iterate until a terminator etc.