Logo
Articles Compilers Libraries Books MiniBooklets Assembly C++ Rust Go Linux CPU Others Videos
Advertisement

Article by Ayman Alheraki on April 4 2026 04:18 PM

Comparison stdfor_each vs. Range‑based for Loop

Comparison: std::for_each vs. Range‑based for Loop

Both std::for_each (from <algorithm>) and the range‑based for loop (C++11 and later) iterate over every element of a container. However, they have different strengths, syntax, and ideal use cases. Since your article covers <functional>, std::for_each is especially relevant because it shines when you already have a callable object (like a functor from <functional>) that you want to apply.

1. Basic Syntax

Range‑based forstd::for_each
for (int c : values) { doSomething(c); }std::for_each(values.begin(), values.end(), doSomething);
Clean, built‑in language feature.Algorithm from <algorithm>. Works with any iterator pair.

2. When to Use Each

Use range‑based for when…Use std::for_each when…
You need a simple, readable loop for most cases.You already have a named function/functor (e.g., std::function, std::mem_fn, std::plus).
You want to break early (break;) or skip (continue;).You want to compose operations with std::bind or use parallel execution (C++17).
You need to modify the loop variable inside (e.g., for (auto& x : vec)).You’re writing generic code that should work with any iterator pair (not just containers).
Performance is critical and you want zero overhead (compilers optimise both equally well).You want to combine with other algorithms (e.g., std::transform, std::accumulate) in a functional pipeline.

3. Detailed Comparison Table

FeatureRange‑based forstd::for_each
ReadabilityExcellent for simple iteration.Slightly more verbose, but expressive when using named functions.
Early exitbreak, continue, return (inside function)No – must throw exception or use std::find_if etc.
Iterator flexibilityWorks only on containers with begin()/end().Works on any iterator pair (e.g., raw array, stream iterators).
Parallel execution (C++17)Not available.Yes: std::for_each(std::execution::par, …)
Return valueNone (statement, not expression).Returns the function object (useful for state).
Use with std::functionYou can call a std::function inside the body.Directly accepts any callable, including std::function.
PerformanceIdentical (both are zero‑overhead abstractions).Identical (both inline to same machine code).

4. Examples Side‑by‑Side

Simple transformation (print each element)

 

Using a predefined functor from <functional>

 

Using std::mem_fn with std::for_each

 

Parallel execution (C++17)

 

5. Returning a Stateful Function Object

std::for_each returns the callable after processing. This is useful for accumulating state.

 

With a range‑based for, you would need an external accumulator variable:

 

Both work, but std::for_each encapsulates the state inside the functor.

6. Performance

Both constructs compile to identical assembly for simple operations. There is no performance penalty for using std::for_each – it’s just a template that inlines the loop. The range‑based for is also syntactic sugar for a traditional iterator loop.

Example compiled with -O2 (both produce the same loop):

 

7. Recommendation Summary

  • Prefer range‑based for for most day‑to‑day loops – it’s simpler, supports break, and is very readable.

  • Use std::for_each when:

    • You already have a callable object (e.g., from <functional>) and want to apply it directly.

    • You need parallel execution.

    • You are writing generic code that works with arbitrary iterator pairs.

    • You want to use the return value (stateful functor).

    • You are working in a “functional” style (pipeline of algorithms).

8. Integration with <functional>

std::for_each is a natural partner for <functional> because it directly accepts:

  • std::function objects,

  • results of std::bind,

  • std::mem_fn wrappers,

  • built‑in functors like std::plus, std::greater (though those are unary/binary, so you’d need std::bind or a lambda to adapt them).

Example:

 

But in modern C++, a lambda is often clearer than std::bind. Still, std::for_each remains a valid choice.


Final verdict: Both are excellent tools. Know both and choose the one that makes your code most expressive and maintainable. For teaching <functional>, std::for_each provides a perfect stage to demonstrate callable objects.

Advertisements

Responsive Counter
General Counter
1195538
Daily Counter
2589