C++仿函式(functor)
阿新 • • 發佈:2019-02-16
什麼是仿函式(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[] = {0, 1, 2, 3, 4, 5};
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()const{ return 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