【c++】c++中的for_each和accumulate函数

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_eachaccumulate
谓词仅需一个参数,对参数的处理不需要和[first,last)范围内的其它元素有关联需要两个参数(init,value),对范围内的元素处理有关联
返回结果将谓词返回,谓词中可以存放处理的结果将累加结果返回
总结对范围内的元素进行某种变换调整常用于累加计算范围内的元素的映射
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值