C++中的函數對象(一)

來源:互聯網
上載者:User

標籤:調用   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++中的函數對象(一)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.