Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preferred standard use: range based for or std::for_each

In C++11, there are two loops over all elements (range based for and for_each). Is there any reason to prefer one over the other or are there situations where one is a better fit?

for (auto& elem: container) {   // do something with elem }  std::for_each(container.begin(), container.end(),               [](Elem& elem) {                 // do something with elem               }); 

My idea would be that the first is simpler and is similar to range based loops in other languages while the second also works for sequences that are not complete containers and the second is more similar to other std-algorithms.

like image 856
stefaanv Avatar asked Apr 03 '12 13:04

stefaanv


People also ask

Is std :: For_each faster?

Looping Performance in C++ Today I was testing the performance of a piece of code, which is basically accessing each element in a container within a for loop. But the result is quite shocking because I found the std::for_each version is 10 times faster than the raw loop.

What is range-based C++?

Range-based for loop (since C++11) Executes a for loop over a range. Used as a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container.

What is a range-based for loop How does it differ from a normal for loop?

Basically, range-based loops are faster to be typed (with less characters), while ordinary for loops are more generic. Ordinary 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.


2 Answers

  1. Range-based for is obviously simpler to read and write. It is specialized for this task.

    EDIT: You can break form a range-for without abusing an exception. (Although std::find_if substituted for std::for_each allows this as well.)

  2. std::for_each, ironically, is the alternative which is actually range based and allows you to select particular begin and end values instead of the whole container. (EDIT: This can be hacked around using a simple range class providing begin and end members, such as provided by Boost.)

    Also for_each may be more elegant when otherwise using higher-order functions: it can be used as an argument to bind, and the third argument is already a functor.

Mainly it's a matter of style. Most readers probably prefer to see for ( auto &a : b ) though, and most implementations now support it.

like image 148
Potatoswatter Avatar answered Oct 10 '22 00:10

Potatoswatter


std::for_each returns the functor that has been used internally in the loop, so it provides a clean mechanism to gather some information concerning the elements in the sequence. The range based for loop is just a loop, so any state that is to be used outside of the loop has to be declared outside of that scope. In your example, if the purpose of the of the loops is to mutate each element of the sequence, then there isn't much difference at all. But if you are not using the return value of the for_each then you're probably better off with the simple loop. By the way, the range based loop works on C-style arrays and std::strings too.

This is an example of using the return value of for_each, although it is not a very imaginative or useful one. It is just to illustrate the idea.

#include <iostream> #include <array> #include <algorithm>  struct Foo {   void operator()(int i) { if (i > 4) sum += i;}   int sum{0}; };  int main() {    std::array<int, 10> a{1,2,3,4,5,6,7,8,9,10};   Foo foo = std::for_each(a.begin(), a.end(), Foo());   std::cout << "Sum " << foo.sum << "\n"; } 
like image 45
juanchopanza Avatar answered Oct 10 '22 00:10

juanchopanza