Are there any advantages of std::for_each over for
loop? To me, std::for_each
only seems to hinder the readability of code. Why do then some coding
Like many of the algorithm functions, an initial reaction is to think it's more unreadable to use foreach than a loop. It's been a topic of many flame wars.
Once you get used to the idiom you may find it useful. One obvious advantage is that it forces the coder to separate the inner contents of the loop from the actual iteration functionality. (OK, I think it's an advantage. Other's say you're just chopping up the code with no real benifit).
One other advantage is that when I see foreach, I know that either every item will be processed or an exception will be thrown.
A for loop allows several options for terminating the loop. You can let the loop run its full course, or you can use the break keyword to explicitly jump out of the loop, or use the return keyword to exit the entire function mid-loop. In contrast, foreach does not allow these options, and this makes it more readable. You can just glance at the function name and you know the full nature of the iteration.
Here's an example of a confusing for loop:
for(std::vector<widget>::iterator i = v.begin(); i != v.end(); ++i)
{
/////////////////////////////////////////////////////////////////////
// Imagine a page of code here by programmers who don't refactor
///////////////////////////////////////////////////////////////////////
if(widget->Cost < calculatedAmountSofar)
{
break;
}
////////////////////////////////////////////////////////////////////////
// And then some more code added by a stressed out juniour developer
// *#&$*)#$&#(#)$#(*$&#(&*^$#(*$#)($*#(&$^#($*&#)$(#&*$&#*$#*)$(#*
/////////////////////////////////////////////////////////////////////////
for(std::vector<widgetPart>::iterator ip = widget.GetParts().begin(); ip != widget.GetParts().end(); ++ip)
{
if(ip->IsBroken())
{
return false;
}
}
}
There are a lot of good reasons in other answers but all seem to forget that
for_each
allows you to use reverse or pretty much any custom iterator when for loop always starts with begin()
iterator.
Example with reverse iterator:
std::list<int> l {1,2,3};
std::for_each(l.rbegin(), l.rend(), [](auto o){std::cout<<o;});
Example with some custom tree iterator:
SomeCustomTree<int> a{1,2,3,4,5,6,7};
auto node = a.find(4);
std::for_each(node.breadthFirstBegin(), node.breadthFirstEnd(), [](auto o){std::cout<<o;});
for_each
is more generic. You can use it to iterate over any type of container (by passing in the begin/end iterators). You can potentially swap out containers underneath a function which uses for_each
without having to update the iteration code. You need to consider that there are other containers in the world than std::vector
and plain old C arrays to see the advantages of for_each
.
The major drawback of for_each
is that it takes a functor, so the syntax is clunky. This is fixed in C++11 (formerly C++0x) with the introduction of lambdas:
std::vector<int> container;
...
std::for_each(container.begin(), container.end(), [](int& i){
i+= 10;
});
This will not look weird to you in 3 years.
for_each
allow us to implement Fork-Join pattern . Other than that it supports fluent-interface.
We can add implementation gpu::for_each
to use cuda/gpu for heterogeneous-parallel computing by calling the lambda task in multiple workers.
gpu::for_each(users.begin(),users.end(),update_summary);
// all summary is complete now
// go access the user-summary here.
And gpu::for_each
may wait for the workers work on all the lambda-tasks to finish before executing the next statements.
It allow us to write human-readable code in concise manner.
accounts::erase(std::remove_if(accounts.begin(),accounts.end(),used_this_year));
std::for_each(accounts.begin(),accounts.end(),mark_dormant);
I find for_each to be bad for readability. The concept is a good one but c++ makes it very hard to write readable, at least for me. c++0x lamda expressions will help. I really like the idea of lamdas. However on first glance I think the syntax is very ugly and I'm not 100% sure I'll ever get used to it. Maybe in 5 years I'll have got used to it and not give it a second thought, but maybe not. Time will tell :)
I prefer to use
vector<thing>::iterator istart = container.begin();
vector<thing>::iterator iend = container.end();
for(vector<thing>::iterator i = istart; i != iend; ++i) {
// Do stuff
}
I find an explicit for loop clearer to read and explicity using named variables for the start and end iterators reduces the clutter in the for loop.
Of course cases vary, this is just what I usually find best.
If you frequently use other algorithms from the STL, there are several advantages to for_each
:
Unlike a traditional for loop, for_each
forces you to write code that will work for any input iterator. Being restricted in this way can actually be a good thing because:
for_each
.Using for_each
sometimes makes it more obvious that you can use a more specific STL function to do the same thing. (As in Jerry Coffin's example; it's not necessarily the case that for_each
is the best option, but a for loop is not the only alternative.)