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 standards recommend its use?
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Why does const allow implicit conversion of refere
- thread_local variables initialization
- What uses more memory in c++? An 2 ints or 2 funct
相关文章
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- How to use doMC under Windows or alternative paral
- Selecting only the first few characters in a strin
- What exactly do pointers store? (C++)
- Converting glm::lookat matrix to quaternion and ba
Here are some reasons:
It seems to hinder readability just because you're not used to it and/or not using the right tools around it to make it really easy. (see boost::range and boost::bind/boost::lambda for helpers. Many of these will go into C++0x and make for_each and related functions more useful.)
It allows you to write an algorithm on top of for_each that works with any iterator.
It reduces the chance of stupid typing bugs.
It also opens your mind to the rest of the STL-algorithms, like
find_if
,sort
,replace
, etc and these won't look so strange anymore. This can be a huge win.Update 1:
Most importantly, it helps you go beyond
for_each
vs. for-loops like that's all there is, and look at the other STL-alogs, like find / sort / partition / copy_replace_if, parallell execution .. or whatever.A lot of processing can be written very concisely using "the rest" of for_each's siblings, but if all you do is to write a for-loop with various internal logic, then you'll never learn how to use those, and you'll end up inventing the wheel over and over.
And (the soon-to-be available range-style for_each):
Or with C++x11 lambdas:
is IMO more readable than:
Also this (or with lambdas, see others):
Is more concise than:
Especially if you have several functions to call in order... but maybe that's just me. ;)
Update 2: I've written my own one-liner wrappers of stl-algos that work with ranges instead of pair of iterators. boost::range_ex, once released, will include that and maybe it will be there in C++0x too?
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++0x with the introduction of lambdas:
This will not look weird to you in 3 years.
Mostly you'll have to iterate over the whole collection. Therefore I suggest you write your own for_each() variant, taking only 2 parameters. This will allow you to rewrite Terry Mahaffey's example as:
I think this is indeed more readable than a for loop. However, this requires the C++0x compiler extensions.
for_each
allow us to implement Fork-Join pattern . Other than that it supports fluent-interface.fork-join pattern
We can add implementation
gpu::for_each
to use cuda/gpu for heterogeneous-parallel computing by calling the lambda task in multiple workers.And
gpu::for_each
may wait for the workers work on all the lambda-tasks to finish before executing the next statements.fluent-interface
It allow us to write human-readable code in concise manner.
The
for_each
loop is meant to hide the iterators (detail of how a loop is implemented) from the user code and define clear semantics on the operation: each element will be iterated exactly once.The problem with readability in the current standard is that it requires a functor as the last argument instead of a block of code, so in many cases you must write specific functor type for it. That turns into less readable code as functor objects cannot be defined in-place (local classes defined within a function cannot be used as template arguments) and the implementation of the loop must be moved away from the actual loop.
Note that if you want to perform an specific operation on each object, you can use
std::mem_fn
, orboost::bind
(std::bind
in the next standard), orboost::lambda
(lambdas in the next standard) to make it simpler:Which is not less readable and more compact than the hand rolled version if you do have function/method to call in place. The implementation could provide other implementations of the
for_each
loop (think parallel processing).The upcoming standard takes care of some of the shortcomings in different ways, it will allow for locally defined classes as arguments to templates:
Improving the locality of code: when you browse you see what it is doing right there. As a matter of fact, you don't even need to use the class syntax to define the functor, but use a lambda right there:
Even if for the case of
for_each
there will be an specific construct that will make it more natural:I tend to mix the
for_each
construct with hand rolled loops. When only a call to an existing function or method is what I need (for_each( v.begin(), v.end(), boost::bind( &Type::update, _1 ) )
) I go for thefor_each
construct that takes away from the code a lot of boiler plate iterator stuff. When I need something more complex and I cannot implement a functor just a couple of lines above the actual use, I roll my own loop (keeps the operation in place). In non-critical sections of code I might go with BOOST_FOREACH (a co-worker got me into it)Personally, any time I'd need to go out of my way to use
std::for_each
(write special-purpose functors / complicatedboost::lambda
s), I findBOOST_FOREACH
and C++0x's range-based for clearer:vs