標籤:調用 init 種類 get sdn names 高效 ref 參考
STL中的函數對象,大多數STL類屬演算法(以及某些容器類)可以以一個函數對象作為參數。引入函數對象的目的是為了使演算法的功能富於變化,從而增強演算法的通用性。
所謂函數對象,是指一段代碼實體,它可以不帶參數,也可以帶有若干參數,其功能是獲得一個值,或者改變操作的狀態。在C++編程中,任何普通的函數都滿足這個定義,而且,任何一個重載了運算子operator()的類的對象也都滿足這一定義,稱為函數對象。
普通函數
int multfun(int x, int y){ return x*y;}
或者下面所定義的multiply類型的對象multfunobj
class multiply{public: int operator()(int x, int y) const {return x*y;} };
multiply multfunobj;
上面的兩種方式,都可以用下面的方式調用:
int product1 = multfun(3, 7);
int product2 = multfunobj(3, 7);
1.通過函數指標傳遞函數參數
#include <iostream>#include <cassert>#include <vector>using namespace std;int multfun(int x, int y){ return x*y;}template <typename InputIterator, typename T>T accumulate1(InputIterator first, InputIterator last, T init, T(*binary_function)(T x, T y)){ while(first != last) { init = (*binary_function)(init, *first); ++first; } return init;}int main(){ cout << "Demonstrating function pointer passing." << endl; int x[5] = {2, 3, 5, 7, 11}; vector<int> vector1(&x[0], &x[5]); int product = accumulate1(vector1.begin(), vector1.end(), 1, &multfun); assert (product == 2310); cout << "---- OK."<<endl; return 0;}
輸出--- OK
這種傳統實現方式的一個基本問題是其通用性不夠強,例如,函數指標原型可以寫成
T (*binary_function)(T x, T y);
並且可以和int multifun(int ,int)匹配,但是,如果寫成 T (*binary_function)(const T& x, const T& y);以便使其在T類對象比較大的情況下具有較高效率,則multifun將無法與之匹配,此時必須以原型 int multifun(const int&, cosnt int& )對函數進行重寫。
另外個問題,在於效率上的,在accumulate1中,必須通過一個指標才能訪問以參數形式傳遞進來的函數,而且只能外聯(out of line)地調用該函數(首先向函數傳遞參數,然後把控制權移交給函數,並且把傳回值拷貝到調用域中,最後把控制移交給函數的調用域)。在被調用函數為mutifun的情況下,函數內部的計算只需要一兩個機器指令,而這些步驟的開銷卻要大的多。
2.通過模板參數定義函數對象的優越性
#include <iostream>#include <cassert>#include <vector>using namespace std;template <typename InputIterator, typename T, typename BinaryFunction>T accumulate (InputIterator first, InputIterator last, T init, BinaryFunction binary_function){ while(first != last) { init = binary_function(init, *first); ++first; } return init;}class multiply{public: int operator()(int x, int y) const {return x*y;} }; multiply multfunobj;int main(){ cout << "Demonstrating function pointer passing." << endl; int x[5] = {2, 3, 5, 7, 11}; vector<int> vector1(&x[0], &x[5]); int product = accumulate(vector1.begin(), vector1.end(), 1, multfunobj); assert(product == 2310); cout << "------ OK"<< endl; return 0;}
accumulate的這種定義下,該函數的最後一個實際參數只需要滿足:帶兩個參數,其類型分別為T1和T2,其中類型T可以轉換為T1,inputIterator的實值型別可以轉換為T2,
且該參數的傳回值類型可以轉換為T,這樣一來,與函數指標傳遞的過於嚴格的類型要求相比,這樣的定義方式可以接受更多種類的函數原型。
在效能方面,由於通過模板參數和重載operator()定義了可以作為參數傳遞的函數對象,因此編譯器可以把binary_function函數調用內聯(inline)在accumulate函數體中,
從而徹底消除了指標解析和外聯調用所帶來的額外開銷。
此外,類定義中還可以定義一些額外的資訊,這樣類的對象就攜帶了一些額外的資訊。
接下來我們就對類對象的一些基本用法進行簡單舉例。
參考《標準模板庫自修教程與參考手冊——STL進行C++編程》
參考:http://blog.csdn.net/bonchoix/article/details/8050627
C++中的函數對象(一)