for_each() 是一个遍历算法,它对指定范围内的每个元素执行给定的可调用对象(仿函数、Lambda 表达式、函数指针),并返回该可调用对象,以便获取其最终状态。
#include <algorithm>
for_each(InputIterator first, InputIterator last, Function fn);1 普通函数 #
向 std::for_each 传入普通函数时,函数名会自动转换为指向该函数的指针。
#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 仿函数 #
仿函数(函数对象) 是重载了函数调用操作符 () 的类对象,它们可以像普通函数一样被调用,但对象内部存储的数据成员使其具有状态。
#include <iostream>
#include <vector>
#include <algorithm>
class Sum {
private:
int total = 0;
public:
void operator()(int n) {
total += n;
}
int getTotal() const { return total; }
};
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
Sum sum = std::for_each(vec.begin(), vec.end(), Sum());
std::cout << sum.getTotal() << std::endl;
return 0;
}以上
Sum()是临时对象,for_each()返回的是修改后的函数对象
// 错误写法
Sum s;
std::for_each(vec.begin(), vec.end(), s); // 传入的是 s 的拷贝
// s.total 还是 0,因为修改的是拷贝
// 正确写法
Sum s;
std::for_each(vec.begin(), vec.end(), std::ref(s)); // 传引用
3 Lambda 表达式 #
Lambda 表达式是 C++11 引入的一种创建匿名函数对象的简洁语法,它允许在函数内部直接定义可调用代码块,并能通过捕获列表访问其作用域内的变量。
[captures] (params) lambda-specifiers -> return type { body }captures 捕获列表,可以把上下文变量以值或引用的方式捕获,在 body 中使用
params 形参列表,可以省略,表示无参函数
lambda-specifiers 说明符,可选项有 mutable exception 等
return type 返回值类型,可以省略,由编译器自动推导
body 函数体,函数实现,可以为空,但是不能省略 {}
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 1. 统计偶数个数(按引用捕获外部作用域中所有变量)
int evenCount = 0;
std::for_each(vec.begin(), vec.end(),
[&](int n) { if (n % 2 == 0) evenCount++; }
);
std::cout << "evenCount: " << evenCount << std::endl;
// 2. 修改容器元素(用引用)
std::for_each(vec.begin(), vec.end(),
[](int &n) { n *= 5; }
);
// 3. 打印每个元素
std::for_each(vec.begin(), vec.end(),
[](int n) { std::cout << n << " "; }
);
std::cout << std::endl;
return 0;
}4 函数指针 #
函数指针是指向函数的指针变量,它可以存储函数的地址,并通过该指针调用函数。
// 返回值类型 (*函数指针名)(参数列表)
#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. 直接使用函数名(函数名自动转换为指针)
line();
std::for_each(vec.begin(), vec.end(), print);
// 2. 声明函数指针变量(指向接受一个 int&、返回 int 的函数)
line();
int (*printPtr)(int&) = print;
std::for_each(vec.begin(), vec.end(), printPtr);
// 3. 定义一个函数,接受函数指针作为参数
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. 函数指针数组
line();
int (*operations[])(int&) = {square, print};
for (auto op : operations) {
std::for_each(vec.begin(), vec.end(), op);
}
// 5. 函数指针与 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. 使用 typedef 简化
line();
typedef int (*PrintFunc)(int&);
PrintFunc pf = print;
std::for_each(vec.begin(), vec.end(), pf);
// 7. 使用 using 简化
line();
using UnaryOp = int(*)(int&);
UnaryOp uop = print;
std::for_each(vec.begin(), vec.end(), uop);
return 0;
}