STL算法(for_each/transform)
### STL算法:for_each与transform详解 #### 一、for_each算法 `for_each` 是C++标准模板库(STL)中的一个非常实用的算法,主要用于遍历容器中的每个元素,并对这些元素执行指定的操作。这使得代码更加简洁且易于维护。 **1.1 函数定义** ```cpp template<class _InIt, class _Fn1> _Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func) {//perform function for each element _DEBUG_RANGE_PTR(_First, _Last, _Func); _For_each_unchecked(_Unchecked(_First), _Unchecked(_Last), _Func); return(_Func); } ``` 其中: - `_InIt`: 迭代器类型,通常为容器中元素的迭代器类型。 - `_Fn1`: 单参数函数对象类型,用于定义操作。 - `_First`: 指向序列起始位置的迭代器。 - `_Last`: 指向序列结束位置的迭代器。 - `_Func`: 要执行的单参数函数对象。 **1.2 工作原理** `for_each`函数会遍历`[first, last)`区间内的所有元素,并将每个元素传递给函数对象`_Func`进行处理。该函数最终返回经过调用后的`_Func`对象。 **1.3 示例代码分析** ```cpp struct PrintV { private: int count; public: void operator()(int &value) { count++; value++; cout << value << " "; } void print() { cout << "调用次数 " << count << endl; } }; void print(vector<int> v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } } int main() { vector<int> v; v.push_back(1); v.push_back(3); v.push_back(2); v.push_back(5); v.push_back(4); print(v); // 输出原始数据 cout << endl; PrintV pv = for_each(v.begin(), v.end(), PrintV()); // 使用for_each处理数据 cout << endl; pv.print(); // 输出调用次数 print(v); // 输出处理后数据 return 0; } ``` **1.4 作用与应用场景** - **简化循环**: `for_each`可以替代传统for循环来遍历容器,使代码更简洁。 - **执行特定操作**: 可以通过提供自定义函数对象实现特定功能,如打印、修改等。 #### 二、transform算法 `transform` 是STL中的另一个重要算法,其主要功能是将一个或两个范围的数据转换到另一个范围中。它可以使用单个输入迭代器,也可以同时使用两个输入迭代器和一个输出迭代器。 **2.1 函数定义** ```cpp template<class _InIt, class _OutIt, class _Fn1> _OutIt transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func) {//transform [_First, _Last) with _Func _DEPRECATE_UNCHECKED(transform, _Dest); return(_Transform_no_deprecate(_First, _Last, _Dest, _Func)); } ``` 其中: - `_InIt`: 输入迭代器类型。 - `_OutIt`: 输出迭代器类型。 - `_Fn1`: 变换函数类型。 - `_First`: 输入序列起始位置的迭代器。 - `_Last`: 输入序列结束位置的迭代器。 - `_Dest`: 输出序列起始位置的迭代器。 - `_Func`: 要应用的变换函数。 **2.2 与for_each的区别** - `for_each`的函数对象可以返回`void`,而`transform`的函数对象必须返回一个值。 - `for_each`的函数对象接受一个引用作为参数,而`transform`的函数对象最好接受值传递。 **2.3 示例代码分析** ```cpp struct TranFunc2 { private: int count; public: int operator()(const int &left, const int &right) { count++; cout << "left right " << left << " " << right << endl; return left + right; } void print() { cout << "调用次数 " << count << endl; } }; void print(vector<int> v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } int main() { vector<int> v1 = {1, 2, 3, 4, 5}; vector<int> v2 = {6, 7, 8, 9, 10}; vector<int> v3(5); transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), TranFunc2()); print(v3); // 输出转换后的结果 TranFunc2().print(); // 输出调用次数 } ``` **2.4 作用与应用场景** - **数据转换**: `transform`常用于数据的转换或计算,如数组的加法、乘法等。 - **高效处理**: 通过将输入和输出分离,提高了并行处理的能力。 - **灵活性**: 支持多种数据结构和运算方式。 ### 总结 `for_each`和`transform`都是STL中非常有用的算法。它们通过简洁的语法实现了对容器数据的有效操作。`for_each`主要用于遍历和修改容器中的元素,而`transform`则侧重于将一个或多个范围的数据转换到新的范围中。掌握这两种算法的应用场景和使用方法,有助于提高编程效率和代码质量。