C++仿函數(functor)

什麼是仿函數(functor)

    functor的英文解釋爲something that performs a function,即其行爲相似函數的東西。C++中的仿函數是經過在類中重載()運算符實現,使你能夠像使用函數同樣來建立類的對象。算法

仿函數(functor)的實現及使用
// 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的示例:
性能

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;
}

  • 參數可設置this

    能夠很容易經過給仿函數(functor)設置參數,來實現本來函數指針才能實現的功能,看下面代碼:spa

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;
};

    這個仿函數的功能是求給定值平方或立方運算的平均值。只須要這樣來聲明一個對象便可:指針

CalculateAverageOfPowers my_cal(2);

  • 有狀態
    code

    與普通函數另外一個區別是仿函數(functor)是有狀態的,因此能夠進行諸以下面這種操做:
orm

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);

    對多個不一樣的數據集進行取平均。對象

  • 性能
    element

    咱們看一下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)可讓這種實現變的更加簡單。

相關文章
相關標籤/搜索