for_each() is a traversal algorithm that executes a given callable object (functor, lambda expression, function pointer) on each element within a specified range and returns that callable object to obtain its final state.
#include <algorithm>
for_each(InputIterator first, InputIterator last, Function fn);1 Ordinary Function #
When an ordinary function is passed to std::for_each, the function name is automatically converted to a pointer to that function.
#include <iostream>
#include <vector>
#include <algorithm>
void print(int n) {
std::cout << n << " ";
}
void doubleValue(int &n) {
n *= 2;
}
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::for_each(vec.begin(), vec.end(), doubleValue);
std::for_each(vec.begin(), vec.end(), print);
return 0;
}2 Functors #
Functional functions (function objects) are class objects that overload the function call operator (). They can be called like ordinary functions, but the data members stored inside the object give them state.
#include <iostream>
#include <vector>
#include <algorithm>
void print(int n) {
std::cout << n << " ";
}
void doubleValue(int &n) {
n *= 2;
}
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::for_each(vec.begin(), vec.end(), doubleValue);
std::for_each(vec.begin(), vec.end(), print);
return 0;
}The above
Sum()is a temporary object,for_each()returns the modified function object.
// Incorrect syntax
Sum s;
std::for_each(vec.begin(), vec.end(), s); // Passes a copy of s
// s.total is still 0 because it modifies the copy
// Correct way to write it
Sum s;
std::for_each(vec.begin(), vec.end(), std::ref(s)); // Passes by reference
3 Lambda Expressions #
Lambda expressions are a concise syntax introduced in C++11 for creating anonymous function objects. They allow you to define callable blocks of code directly inside a function and access variables within their scope through a capture list.
[captures] (params) lambda-specifiers -> return type { body }captures Capture list, can capture context variables by value or reference, used in the body.
params Parameter list, can be omitted, indicating a parameterless function.
lambda-specifiers Specifiers, options include mutable, exception, etc.
return type Return type, can be omitted, automatically inferred by the compiler.
body Function body, function implementation, {} can be empty, but cannot be omitted.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 1. Count the number of even numbers (capture all variables in the outer scope by reference)
int evenCount = 0;
std::for_each(vec.begin(), vec.end(),
[&](int n) { if (n % 2 == 0) evenCount++; }
);
std::cout << "evenCount: " << evenCount << std::endl;
// 2. Modify container elements (using references)
std::for_each(vec.begin(), vec.end(),
[](int &n) { n *= 5; }
);
// 3. Print each element
std::for_each(vec.begin(), vec.end(),
[](int n) { std::cout << n << " "; }
);
std::cout << std::endl;
return 0;
}4 Function Pointers #
A function pointer is a pointer variable that points to a function. It can store the address of a function and can be used to call the function.
// Return value type (*function pointer name)(parameter list)
#include <iostream>
#include <vector>
#include <algorithm>
int print(int& n) {
std::cout << n << " ";
return 0;
}
int square(int& n) {
return n *= n;
}
class Line {
private:
int cnt = 0;
public:
void operator()() {
cnt++;
std::cout << std::endl << std::endl;
std::cout << "------ " << cnt << " ------" << std::endl;
}
};
int main() {
Line line;
std::vector<int> vec = {1, 2, 3, 4, 5};
// 1. Directly using the function name (function name is automatically converted to a pointer)
line();
std::for_each(vec.begin(), vec.end(), print);
// 2. Declare a function pointer variable (pointing to a function that accepts an int& and returns an int)
line();
int (*printPtr)(int&) = print;
std::for_each(vec.begin(), vec.end(), printPtr);
// 3. Define a function that accepts a function pointer as an argument
line();
auto processVector = [](std::vector<int>& v, int (*func)(int&)) {
std::for_each(v.begin(), v.end(), func);
};
processVector(vec, square);
processVector(vec, printPtr);
// 4. Array of function pointers
line();
int (*operations[])(int&) = {square, print};
for (auto op : operations) {
std::for_each(vec.begin(), vec.end(), op);
}
// 5. Combining function pointers with transform
line();
int (*squarePtr)(int&) = square;
std::vector<int> result(vec.size());
std::transform(vec.begin(), vec.end(), result.begin(), squarePtr);
std::for_each(result.begin(), result.end(), print);
// 6. Simplifying with typedef
line();
typedef int (*PrintFunc)(int&);
PrintFunc pf = print;
std::for_each(vec.begin(), vec.end(), pf);
// 7. Simplifying with using
line();
using UnaryOp = int(*)(int&);
UnaryOp uop = print;
std::for_each(vec.begin(), vec.end(), uop);
return 0;
}