for_each函数
for_each函数定义在<algorithm>
头文件中,其函数声明为:
template<class InputIt, class UnaryFunction>
constexpr UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
{
for (; first != last; ++first) {
f(*first);
}
return f; // implicit move since C++11
}
接收两个迭代器first,last,并对[first,last)范围内的元素遍历,传递给函数或函数对象f,遍历结束返回函数或函数对象f
f可以是一个函数,一个函数对象,或者是一个lambda表达式
用函数作为谓词
void print(const int &a) {
cout << a << " ";
}
int main() {
std::vector<int> nums{3, 4, 2, 8, 15, 267};
// for_each函数遍历完之后,会把谓词返回
void (*pfunc)(const int &) = for_each(nums.begin(), nums.end(), print);
cout << endl;
pfunc(6);
}
用函数对象作为谓词
只要是重载了()
运算符的类或者结构体,就是函数对象类,该类的实例即为函数对象。
结构体中成员属性和成员方法默认为public
类中成员属性和成员方法默认为private
struct Sum {
Sum() : sum{0} {}
// 重载()运算符
void operator()(int n) { sum += n; }
int sum;
};
std::vector<int> nums{3, 4, 2, 8, 15, 267};
//将容器中的元素遍历分别传递给函数对象进行累加,遍历结束返回该函数对象
Sum s = std::for_each(nums.begin(), nums.end(), Sum());
//从函数对象中获取累加结果
std::cout << "sum: " << s.sum << '\n';
用lambda表达式作为谓词
std::vector<int> nums{3, 4, 2, 8, 15, 267};
void (*pfunc)(const int &) = for_each(nums.begin(), nums.end(), [](const int &n) { cout << n << " "; });
cout << endl;
pfunc(7);
accumulate函数
accumulate函数定义在numeric
头文件中,其函数定义有两种:
第一种实现就是累加[first,last)范围内的元素,init+=*first
并返回累加结果
template<class InputIt, class T>
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = std::move(init) + *first; // std::move since C++20
}
return init;
}
第二种实现累加规则不一样了,累加规则可以在谓词里面定义,init = op(std::move(init), *first)
并返回累加结果
template<class InputIt, class T, class BinaryOperation>
T accumulate(InputIt first, InputIt last, T init,
BinaryOperation op)
{
for (; first != last; ++first) {
init = op(std::move(init), *first); // std::move since C++20
}
return init;
}
用函数作为谓词
// 注意lhs和rhs的顺序!!!
int op_sum(int total, int value) {
return total + value * value;
}
vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for_each(v.begin(), v.end(), [](const int &n) { cout << n << " "; });
// 使用默认累加
cout << accumulate(v.begin(), v.end(), 0) << endl;
// 使用函数作为谓词,计算平方和
cout << accumulate(v.begin(), v.end(), 0, op_sum) << endl;
用函数对象作为谓词
template<typename T>
class OpSum {
private:
int power;
public:
explicit OpSum(int p) : power(p) {}
T operator()(const T &total, const T &value) { //计算 value的power次方,加到total上
return total + pow(value, power);
}
};
vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for_each(v.begin(), v.end(), [](const int &n) { cout << n << " "; });
// 使用默认累加
cout << accumulate(v.begin(), v.end(), 0) << endl;
// 使用函数对象作为谓词,计算平方和
cout << accumulate(v.begin(), v.end(), 0, OpSum<int>(2)) << endl;
用lambda表达式作为谓词
vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for_each(v.begin(), v.end(), [](const int &n) { cout << n << " "; });
// 使用默认累加
cout << accumulate(v.begin(), v.end(), 0) << endl;
// 使用lambda作为谓词,计算平方和
cout << accumulate(v.begin(), v.end(), 0, [](const int &total, const int &value) { return total + value * value; })
<< endl;
对于一些简单的需求,我们可以用默认累加或者lambda表达式一行搞定,当然,如果需要更加复杂的需求,比如累加规则多样,甚至想对不同的数据类型累加规则,那么推荐使用函数对象。
全部代码如下:
//函数对象
#include <iostream>
#include <vector>
#include <numeric> //accumulate 在此头文件定义
#include <algorithm>
#include <cmath>
using namespace std;
// 注意lhs和rhs的顺序!!!
int op_sum(int total, int value) {
return total + value * value;
}
template<typename T>
class OpSum {
private:
int power;
public:
explicit OpSum(int p) : power(p) {}
T operator()(const T &total, const T &value) { //计算 value的power次方,加到total上
return total + pow(value, power);
}
};
int main() {
vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for_each(v.begin(), v.end(), [](const int &n) { cout << n << " "; });
// 使用默认累加
cout << accumulate(v.begin(), v.end(), 0) << endl;
// 使用函数作为谓词,计算平方和
cout << accumulate(v.begin(), v.end(), 0, op_sum) << endl;
// 使用函数对象作为谓词,计算平方和
cout << accumulate(v.begin(), v.end(), 0, OpSum<int>(2)) << endl;
// 使用lambda作为谓词,计算平方和
cout << accumulate(v.begin(), v.end(), 0, [](const int &total, const int &value) { return total + value * value; })
<< endl;
return 0;
}
对比
for_each | accumulate | |
---|---|---|
谓词 | 仅需一个参数,对参数的处理不需要和[first,last)范围内的其它元素有关联 | 需要两个参数(init,value),对范围内的元素处理有关联 |
返回结果 | 将谓词返回,谓词中可以存放处理的结果 | 将累加结果返回 |
总结 | 对范围内的元素进行某种变换调整 | 常用于累加计算范围内的元素的映射 |