C++仿函数(functor)

转自http://my.oschina.net/llehs/blog/180594,作者:雪让



什么是仿函数(functor)

    functor的英文解释为something that performs a function,即其行为类似函数的东西。C++中的仿函数是通过在类中重载()运算符实现,使你可以像使用函数一样来创建类的对象。

仿函数(functor)的实现及使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// this is a functor
struct  add_x {
   add_x( int  x) : x(x) {}
   int  operator()( int  y) {  return  x + y; }
private :
   int  x;
};
// usage:
add_x add42(42);  // create an instance of the functor class
int  i = add42(8);  // and "call" it
assert (i == 50);  // and it added 42 to its argument
std::vector< int > in;  // assume this contains a bunch of values)
std::vector< int > out;
// Pass a functor to std::transform, which calls the functor on every element 
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1)); 
assert (out[i] == in[i] + 1);  // for all i

为什么使用仿函数(functor)
  • 迭代和计算逻辑分离

    使用仿函数可以使迭代和计算分离开来。因而你的functor可以应用于不同场合,在STL的算法中就大量使用了functor,下面是STL中for_each中使用functor的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct  sum
{
     sum( int  * t):total(t){};
     int  * total;
     void  operator()( int  element)
     {
        *total+=element;
     }
};
int  main()
{
     int  total = 0;
     sum s(&total);
     int  arr[] = {0, 1, 2, 3, 4, 5};
     std::for_each(arr, arr+6, s);
     cout << total << endl;  // prints total = 15;
}

  • 参数可设置

    可以很容易通过给仿函数(functor)设置参数,来实现原本函数指针才能实现的功能,看下面代码:

1
2
3
4
5
6
7
8
9
10
11
class  CalculateAverageOfPowers
{
public :
     CalculateAverageOfPowers( float  p) : acc(0), n(0), p(p) {}
     void  operator() ( float  x) { acc +=  pow (x, p); n++; }
     float  getAverage()  const  return  acc / n; }
private :
     float  acc;
     int    n;
     float  p;
};

    这个仿函数的功能是求给定值平方或立方运算的平均值。只需要这样来声明一个对象即可:

1
CalculateAverageOfPowers my_cal(2);

  • 有状态

    与普通函数另一个区别是仿函数(functor)是有状态的,所以可以进行诸如下面这种操作:

1
2
3
4
CalculateAverage avg;
avg = std::for_each(dataA.begin(), dataA.end(), avg);
avg = std::for_each(dataB.begin(), dataB.end(), avg);
avg = std::for_each(dataC.begin(), dataC.end(), avg);

    对多个不同的数据集进行取平均。

  • 性能

    我们看一下2中写的代码:

1
std::transform(in.begin(), in.end(), out.begin(), add_x(1));

    编译器可以准确知道std::transform需要调用哪个函数(add_x::operator)。这意味着它可以内联这个函数调用。而如果使用函数指针,编译器不能直接确定指针指向的函数,而这必须在程序运行时才能得到并调用。

    一个例子就是比较std::sort 和qsort ,STL的版本一般要快5-10倍。

  • 总结

    当然,前3点都可以使用传统的函数和指针实现,但是用仿函数(functor)可以让这种实现变的更加简单。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值