STL for_each 和函数对象(function object) 使用详解

STL for_each函数定义在头文件<algorithm>里面, 其实现很简单, 如下:
[cpp]  view plain copy
  1. template<class _InIt, class _Fn1>  
  2. _Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)  
  3. {// perform function for each element  
  4.     for (; _First != _Last; ++_First)  
  5.         _Func(*_First);  //Note!  
  6.     return (_Func);  
  7. }  


for_each函数接受3个参数, 前两个是STL容器的向前迭代器, 第三个参数是一个函数对象( 函数对象就是重载了operator()的类对象 , 这样在构造了对象func后可以采用形如func(args...)的方式调用, 类似于函数, 所以函数对象又称伪函数)。注意上面的代码_Func(*_First), 这行代码表示了该函数对象重载了只接受一个参数的operator()。for_each函数循环将容器中的元素传递给函数对象, 通过函数对象的operator()的具体实现来执行相应操作, 这就给我们提供了很灵活的用法。


用法示例:

[html]  view plain copy
  1. //这是取自MSDN的一个例子  
  2. // The function object to determine the average  
  3. class Average  
  4. {  
  5. private:  
  6.    long num;      // The number of elements  
  7.    long sum;      // The sum of the elements  
  8. public:  
  9.    // Constructor initializes the value to multiply by  
  10.    Average ( ) : num ( 0 ) , sum ( 0 )  
  11.    {  
  12.    }  
  13.   
  14.    // The function call to process the next elment  
  15.    void operator ( ) ( int elem ) \  
  16.    {  
  17.       num++;      // Increment the element count  
  18.       sum += elem;   // Add the value to the partial sum  
  19.    }  
  20.   
  21.    // return Average  //默认double类型转换  
  22.    operator double ( )  
  23.    {  
  24.       return  static_cast <double> (sum) /  
  25.       static_cast <double> (num);  
  26.    }  
  27. };  
[html]  view plain copy
  1. //这里是调用  
  2. vector <int> v1;  
  3. ...  
  4. double avemod2 = for_each ( v1.begin ( ) , v1.end ( ) , Average ( ) );  
  5. cout << "The average of the elements of v1 is:\n Average ( v1mod2 ) = "   
  6.     << avemod2 << "." << endl;  

 

这里函数对象Average将vector v1中的元素累加到自身, 通过for_each返回该函数对象的拷贝, 在将函数对象赋值给double类型变量avemod2的时候调用自定义默认类型转换运算符函数operator double(), 该函数通过自身累加数据返回平均值。通过这个例子我们可以感受到for_each结合函数对象的神奇妙用。

 

函数对象的构造

STL有一些函数可以用来专门构造特定的函数对象, 这些函数定义在<functional> <xfunctional>里面,常用的如:

ptr_fun 可以将C式函数转换为函数对象pointer_to_unary_funciton, pointer_to_binary_function, 这些函数对象的operator()接受参数和原函数相同

mem_fun, mem_fun1可以将C++类成员函数转换为函数对象mem_fun_t, mem_fun1_t。这些函数对象的operator() 接受类对象的指针, 所以传递给for_each的时候要注意容器中的元素应为对象指针。

mem_fun_ref, mem_fun1_ref 可以将C++类成员函数转换为函数对象mem_fun_ref_t, mem_fun1_ref_t。这俩函数功能与上面两个相同,只是这些函数对象的operator() 接受类对象的ref。

 

由于for_each接受的函数对象要求operator()只接受一个参数, STL还提供了2个很常用的函数:bind1st, bind2nd, 将双参数的函数对象的其中一个参数和一个变量或值关联起来, 返回一个只接受一个参数的函数对象。

 

以上提到函数详情请查阅MSDN和STL源码, 下面再贴一个例子, 依然取自MSDN:

[cpp]  view plain copy
  1. // functional_mem_fun.cpp  
  2. // compile with: /EHsc  
  3. #include <vector>  
  4. #include <functional>  
  5. #include <algorithm>  
  6. #include <iostream>  
  7.   
  8. using namespace std;  
  9.   
  10. class StoreVals     
  11. {  
  12.     int val;  
  13. public:  
  14.     StoreVals() { val = 0; }  
  15.     StoreVals(int j) { val = j; }  
  16.   
  17.     bool display() { cout << val << " "return true; }  
  18.     int squareval() { val *= val; return val; }  
  19.     int lessconst(int k) {val -= k; return val; }  
  20. };  
  21.   
  22. int main( )  
  23. {  
  24.     vector<StoreVals *> v1;  
  25.   
  26.     StoreVals sv1(5);  
  27.     v1.push_back(&sv1);  
  28.     StoreVals sv2(10);  
  29.     v1.push_back(&sv2);  
  30.     StoreVals sv3(15);  
  31.     v1.push_back(&sv3);  
  32.     StoreVals sv4(20);  
  33.     v1.push_back(&sv4);  
  34.     StoreVals sv5(25);  
  35.     v1.push_back(&sv5);  
  36.   
  37.     cout << "The original values stored are: " ;  
  38.     for_each(v1.begin(), v1.end(), mem_fun<bool, StoreVals>(&StoreVals::display));  
  39.     cout << endl;  
  40.   
  41.     // Use of mem_fun calling member function through a pointer  
  42.     // square each value in the vector using squareval ()  
  43.     for_each(v1.begin(), v1.end(), mem_fun<int, StoreVals>(&StoreVals::squareval));     
  44.     cout << "The squared values are: " ;  
  45.     for_each(v1.begin(), v1.end(), mem_fun<bool, StoreVals>(&StoreVals::display));  
  46.     cout << endl;  
  47.   
  48.     // Use of mem_fun1 calling member function through a pointer  
  49.     // subtract 5 from each value in the vector using lessconst ()  
  50.     for_each(v1.begin(), v1.end(), bind2nd (mem_fun1<int, StoreVals,int>(&StoreVals::lessconst), 5));     
  51.     cout << "The squared values less 5 are: " ;  
  52.     for_each(v1.begin(), v1.end(), mem_fun<bool, StoreVals>(&StoreVals::display));  
  53.     cout << endl;  
  54. }  

 

最后一点:

for_each调用函数对象的operator()的时候并不关注operator()的返回值, STL还有其他一些函数实现类似于for_each。根据operator() 的返回值在遍历的时候实现更多的功能。如count_if, find_if等等。


http://blog.csdn.net/lovepal4/article/details/8438462

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值