文章目录
- 一、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请按任意键继续. . .