文章目录

  • 一、for_each 算法
    • 1、for_each 函数简介
    • 2、for_each 函数原型
    • 3、for_each 函数源码分析
    • 4、for_each 函数 _Fn _Func 参数 值传递说明
  • 二、代码示例 – for_each 算法
    • 1、代码示例 – for_each 算法 传入普通函数
    • 2、代码示例 – for_each 算法 传入 Lambda 表达式
    • 3、代码示例 – for_each 算法 传入一元函数对象
    • 4、代码示例 – for_each 算法 函数对象 值传递

一、for_each 算法


1、for_each 函数简介

在 C++ 语言 的 标准模板库 ( STL , Standard Template Library ) 中 , 提供了 for_each 算法 用于 对一个 STL 容器中的每个元素执行某个指定的 ” 操作 ” ;

for_each 算法 中 执行的 ” 操作 ” 可以是一个 函数 / 函数对象 / Lambda 表达式 ;

在 for_each 函数 中 可以修改 被遍历的元素 , 也可以 不修改 元素 ;

2、for_each 函数原型

for_each 算法 函数原型 :迭代器 范围 内的所有元素 传入 一个参数的 可调用对象 , 逐个遍历 执行上述操作 ;

template <class InputIt, class Function>Function for_each(InputIt first, InputIt last, Function f);
  • 参数解析 :
    • InputIt first 参数 : 要遍历的 迭代器范围 的 起始迭代器 , first 参数 是指向序列中 第一个元素 的迭代器 ; 这是 ” 前闭后开区间 ” 的 起始闭区间 ;
    • InputIt last 参数 : 要遍历的 迭代器范围 的 终止迭代器 , last 参数 是指向序列中 最后一个元素 之后 位置 的迭代器 ; 这是 ” 前闭后开区间 ” 的 末尾开区间 ;
    • Function f 参数 : 接收一个参数的可调用对象 , 可以是 一元函数对象 或者 接收一个参数的 普通函数 / Lambda 表达式 , 将 迭代器范围 内的 所有元素 , 传入该 可调用对象 中 ,
    • 迭代器范围 解析 : 是一个 ” 前闭后开区间 “ , 起始迭代器指向的元素包含在范围之内 , 终止迭代器 指向的元素 不包含在范围之内 , 如果 终止迭代器 是 末尾迭代器 end() , 那么 指向无意义元素 ;
  • 返回值解析 : 该算法函数 的 返回值是 传入的函数对象 ;
    • 保存状态 : 如果传入的是 函数对象 , 这一返回值特性使得 作为参数传入的 函数对象 可以在 for_each 调用之后保持其状态 , 这里的 ” 状态 ” 指的是 函数对象 类 中的 成员变量 ; 如果 传入的事 普通函数 或 Lambda 表达式 , 则没有状态 ;
    • 链式调用 : 返回值 是 传入的 可调用对象 本身 , 可用于 实现 ” 链式调用 ” ;

3、for_each 函数源码分析

for_each 源代码如下 :

// FUNCTION TEMPLATE for_eachtemplate <class _InIt, class _Fn>_Fn for_each(_InIt _First, _InIt _Last, _Fn _Func) { // perform function for each element [_First, _Last)_Adl_verify_range(_First, _Last);auto _UFirst= _Get_unwrapped(_First);const auto _ULast = _Get_unwrapped(_Last);for (; _UFirst != _ULast; ++_UFirst) {_Func(*_UFirst);}return _Func;}

该 函数 是一个 ” 模板函数 ” , 第一个 模板类型 _InIt 是 迭代器类型 , 第二个 模板类型 _Fn 是 可调用对象 类型 , 该可调用对象 接收 一个 函数参数 , 可以是 函数对象 / 普通函数 ,

在该 模板函数 中 , 遍历 _InIt _First 和 _InIt _Last 范围的元素 , 传入到 _Func 函数对象 中 , 调用完成后 , 将 _Func 函数对象 返回 , 该函数可进行 链式调用 ;

4、for_each 函数 _Fn _Func 参数 值传递说明

这里特别注意 : 传入的 _Fn _Func 参数 是 函数对象 , 该参数类型是 值 类型 , 不是 引用 或 一维指针 类型 , 因此 该 传入的参数 是 值传递 , 传入参数 是 实参 的副本 ,

也就是 将 函数对象 A 传入到 for_each 函数中 , 此时会将 A 对象 赋值一份副本 B 传入到 for_each 中 , 在 for_each 函数中使用的是 对象 B , 然后返回的也是 对象 B ;

二、代码示例 – for_each 算法


1、代码示例 – for_each 算法 传入普通函数

代码示例 :

#include "iostream"using namespace std;#include #include #include "functional"// 普通函数void printElement(int& n){cout << n << " ";}int main() {// 创建一个 set 集合容器vector<int> myVector;// 向容器中插入元素myVector.push_back(9);myVector.push_back(5);myVector.push_back(2);myVector.push_back(7);myVector.push_back(2);// 向 foreach 循环中传入 Lambda 表达式for_each(myVector.begin(), myVector.end(), printElement);cout << endl;// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;};

执行结果 :

9 5 2 7 2请按任意键继续. . .

2、代码示例 – for_each 算法 传入 Lambda 表达式

代码示例 :

#include "iostream"using namespace std;#include #include #include "functional"int main() {// 创建一个 set 集合容器vector<int> myVector;// 向容器中插入元素myVector.push_back(9);myVector.push_back(5);myVector.push_back(2);myVector.push_back(7);myVector.push_back(2);// 向 foreach 循环中传入 Lambda 表达式for_each(myVector.begin(), myVector.end(), [](int a) {std::cout << a << " ";});cout << endl;// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;};

执行结果 :

9 5 2 7 2请按任意键继续. . .

3、代码示例 – for_each 算法 传入一元函数对象

代码示例 :

#include "iostream"using namespace std;#include #include #include "functional"// 一元函数对象class PrintElement{public:PrintElement(){count = 0;}void operator()(int& n){cout << count << ". " << n << " , ";count++;}private:int count;};int main() {// 创建一个 vector 集合容器vector<int> myVector;// 向容器中插入元素myVector.push_back(9);myVector.push_back(5);myVector.push_back(2);myVector.push_back(7);myVector.push_back(2);// 向 foreach 循环中传入 Lambda 表达式for_each(myVector.begin(), myVector.end(), PrintElement());cout << endl;// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;};

执行结果 :

0. 9 , 1. 5 , 2. 2 , 3. 7 , 4. 2 ,请按任意键继续. . .

4、代码示例 – for_each 算法 函数对象 值传递

代码示例 :

#include "iostream"using namespace std;#include #include #include "functional"// 一元函数对象class PrintElement{public:PrintElement(){count = 0;}void operator()(int& n){cout << count << ". " << n << " , ";count++;}void printCount() {cout << "count = " << count << endl;}private:int count;};int main() {// 创建一个 vector 集合容器vector<int> myVector;// 向容器中插入元素myVector.push_back(9);myVector.push_back(5);myVector.push_back(2);myVector.push_back(7);myVector.push_back(2);// 向 foreach 循环中传入 Lambda 表达式auto PE1 = PrintElement();auto PE2 = for_each(myVector.begin(), myVector.end(), PE1);cout << endl;PE1.printCount();PE2.printCount();// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;};

执行结果 :

0. 9 , 1. 5 , 2. 2 , 3. 7 , 4. 2 ,count = 0count = 5请按任意键继续. . .