1. 程式人生 > >C++仿函式(functor)

C++仿函式(functor)

什麼是仿函式(functor)

    functor的英文解釋為something that performs a function,即其行為類似函式的東西。C++中的仿函式是通過在類中過載()運算子實現,使你可以像使用函式一樣來建立類的物件。

仿函式(functor)的實現及使用
// this is a functor
struct add_x {
  add_x(int x) : x(x) {}
  intoperator()(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的示例:

struct sum
{
    sum(int * t):total(t){};
    int * total;
    voidoperator
()(int element)
{        *total+=element;     } }; intmain(){     int total = 0;     sum s(&total);     int arr[] = {012345};     std::for_each(arr, arr+6, s);     cout << total << endl// prints total = 15; }
  • 引數可設定

    可以很容易通過給仿函式(functor)設定引數,來實現原本函式指標才能實現的功能,看下面程式碼:

class CalculateAverageOfPowers
{
public:
    CalculateAverageOfPowers(float p) : acc(0), n(0), p(p) {}
    voidoperator()(float x){ acc += pow(x, p); n++; }
    floatgetAverage()constreturn acc / n; }
private:
    float acc;
    int   n;
    float p;
};

    這個仿函式的功能是求給定值平方或立方運算的平均值。只需要這樣來宣告一個物件即可:

CalculateAverageOfPowers my_cal(2);
  • 有狀態

    與普通函式另一個區別是仿函式(functor)是有狀態的,所以可以進行諸如下面這種操作:

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中寫的程式碼:

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

    編譯器可以準確知道std::transform需要呼叫哪個函式(add_x::operator)。這意味著它可以內聯這個函式呼叫。而如果使用函式指標,編譯器不能直接確定指標指向的函式,而這必須在程式執行時才能得到並呼叫。

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

  • 總結

    當然,前3點都可以使用傳統的函式和指標實現,但是用仿函式(functor)可以讓這種實現變的更加簡單。

網址:https://my.oschina.net/llehs/blog/180594