【C++】泛型算法之std::for_each

news/2024/11/30 20:46:15/

std::for_each用于逐个遍历容器元素,它对迭代器区间[first, last)所指的每一个元素,执行由单参数函数对象f所定义的操作。它是for循环的一种替代方案。


std::for_each

如需使用std::for_each,需要引入头文件:

#include <algorithm>

std::for_each函数定义:

template< class InputIt, class UnaryFunction >
UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f);

函数意义:按顺序应用给定的可调用对象f[first, last)范围内每个迭代器的结果

函数参数:

  • first、last:应用函数的范围
  • f:可调用对象,应用于范围[first, last]内每个迭代器的结果

对于可调用对象,其函数签名应等同于以下内容:

void fun(const Type &a);

其中,唯一参数也不一定要有const &,但该可调用对象的返回值必须为void

函数返回值:传入的可调用对象的最终状态(C++11后,该返回值为右值)

一般情况下,获得返回值常用于可调用对象为函数对象时(重载了()运算符类型的对象)。

根据语义,std::for_each可能的一种实现是:

template<class InputIt, class UnaryFunction>
constexpr UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
{for (; first != last; ++first) {f(*first);}return std::move(f);
}

std::for_each的优越性

std::for_each更明确了整个循环语义,有利于编译器优化。它偏向于函数式编程,就是老老实实从first迭代到end,没有中途退出循环的break,没有直接跳下一步循环的continue

这个语义清清楚楚,编译器可以尽情优化。相反,如果使用传统的for循环,或者C++11的range-based for,都无法让编译器相信半途中是否会来个break/continue这样的操作。

也就是说,编译器可以从for_each里获得更多的语义。而for循环把这些语义全搞丢了!

因此,std::for_each可以支持并行操作。C++17开始有并行的std::for_each重载了,目前msvc和gcc已经实现,clang还没有实现

template< class ExecutionPolicy, class ForwardIt, class UnaryFunction2 >
void for_each(ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, UnaryFunction2 f);

该函数:应用给定的可调用对象f到[first, last)范围内每个迭代器的结果(不必按顺序),按照policy执行算法

policy指的是允许的并行类型,具体的类型种类可以参考:

  • std::execution::seq, std::execution::par, std::execution::par_unseq, std::execution::unseq

std::for_each实例

#include <iostream>
#include <algorithm>
#include <vector>class Sum {public:Sum() : sum(0) {}~Sum() {}void operator()(int n) { sum += n; }int sum;
};int main()
{std::vector<int> nums{6, 8, 4, 10, 2, 12};auto print = [](int n) {std::cout << n << " ";};std::for_each(nums.begin(), nums.end(), print);                   // 打印std::cout << std::endl;std::for_each(nums.begin(), nums.end(), [](int &n) {              // 每个数++++n;});std::for_each(nums.begin(), nums.end(), print);                   // 打印std::cout << std::endl;Sum s = std::for_each(nums.begin(), nums.end(), Sum());           // 求和std::cout << s.sum << std::endl;int sum = 0;std::for_each(nums.begin(), nums.end(), [&sum](int n) {           // 求和sum += n;});std::cout << sum << std::endl;return 0;
}

编译并运行这段代码:

yngzmiao@yngzmiao-virtual-machine:~/test/foreach$ ./main 
6 8 4 10 2 12 
7 9 5 11 3 13 
48
48

相关阅读

  • C++ STL中 for_each 算法存在的意义是什么?
  • std::for_each - cppreference.com
  • C++中std::for_each的使用

http://www.ppmy.cn/news/706227.html

相关文章

Fluttter的ClipRRect控件

ClipRRect简介 ClipRRect&#xff08;Rounded Rectangle Clip&#xff09;是Flutter中的一个控件&#xff0c;用于将其子控件剪裁为圆角矩形形状。 使用场景 ClipRRect通常在需要给子控件添加圆角效果时使用。它可以用于创建圆角图片、圆角容器等各种UI元素。 主要属性 bo…

gcc/g++/clang/cl编译器

编译器一般构成 传统的编译器通常分为三个部分&#xff0c;前端(frontEnd)&#xff0c;优化器(Optimizer)和后端(backEnd)。在编译过程中&#xff0c;前端主要负责词法和语法分析&#xff0c;将源代码转化为抽象语法树&#xff1b;优化器则是在前端的基础上&#xff0c;对得到…

FM25CL64程序(C51版)

FM25CL64芯片手册&#xff1a;https://wenku.baidu.com/view/dabf5e71168884868762d6aa.html #ifndef FW25CL64_H #define FW25CL64_H#include "reg51.h" #include "intrins.h"#define WREN 0X06 //写使能操作码 #define WRDI 0X04 //写禁止…

移动机器人的运动学模型:差速传动移动机器人

差速传动移动机器人运动学模型 问题 如何根据差速传动机器人左右两边轮子的速度&#xff0c;计算出机器人当前的状态。或者想要以一定速度到达某处&#xff0c;需要给出差速两边轮子的速度指令。 当然大多数时候&#xff0c;购买的机器人底盘能够直接帮助我们执行发送给机器人…

c语言中执行cl exe时出错,执行cl.exe时出错怎么办

执行cl.exe时出错的解决办法:首先打开vc界面;然后依次点击【“TOOLS”-“Option”-“Directories”】;最后重新设置“Excutable Fils、Include Files...”的路径或者修改环境变量即可。 具体问题: 为什么老是“执行 cl.exe 时出错”#include main() {float a = 12.3,b; dou…

课程学习(Curriculum Learning, CL)

原文链接&#xff1a; https://zhuanlan.zhihu.com/p/362351969 A Survey on Curriculum Learning TPAMI 2021 文章目录 问题定义有效性分析1. 模型优化角度数据分布角度 方法总结Predefined CLAutomatic CL 未来研究方向 全文内容导图汇总&#xff1a; 导图&#xff1a; http…

VS报错-- “CL.exe以退出,代码为5“ 解决办法

报错&#xff1a;CL.exe以退出&#xff0c;代码为5 解决办法&#xff1a; 项目属性–VC目录–可执行文件目录 把从父级或项目默认设置继承勾选上 然后在运行就没有问题了

CL-200A串口通信

一.进入串口模式 1.cl-200a关机,开关拨向“O”端 2.hold on键弹出 3.同时按下SET/CALL/CF,并且开关拨向“I”端,这时候会进入USB模式 二.CL-200A通信命令 模式 命令 PC connect02 30 30 35 34 31 20 20 20 03 31 33 0D 0ASet Hold02 39 39 35 35 31 20 20 30 03 30 32 0D…