STL源碼剖析(仿函數/bind2nd)

來源:互聯網
上載者:User

標籤:turn   vector   需要   code   second   src   自己   main   alt   

仿函數(functors)其實就是重載了operator()的對象。

下面簡單先看看它的一個例子:

 1 #include <iostream> 2 using namespace std; 3  4 template<typename T> 5 struct m_plus 6 { 7     T operator()(const T& x, const T& y) { return x + y; } 8 }; 9 10 int main(int argc, char *argv[])11 {12     // 定義其對象  調用其operator()13     m_plus<int> op;14     cout << op(1, 2) << endl;15     // 產生一個匿名對象  這是仿函數的主流用法16     cout << m_plus<int>()(1, 2) << endl;17     return 0;18 }
View Code

 

既然仿函數跟函數的用法類同,那為什麼不直接使用函數指標代替呢?

個人認為有兩個原因

1.仿函數可以有自己的狀態,而函數指標則不行(有的使用template或者static變數可以實現)。

我們可以這樣子使用仿函數:

 1 #include <iostream> 2 using namespace std; 3  4 template<typename T, T add> 5 struct m_plus 6 { 7     m_plus() { _add = add; } 8     T operator()(const T& x) { return x + _add; } 9     // 仿函數可以具有自己的狀態10     int _add;11 };12 13 int main(int argc, char *argv[])14 {15     m_plus<int, 10> op;16     cout << op(100) << endl;17     cout << op(200) << endl;18     return 0;19 }
View Code

 

2.仿函數可以與函數適配器搭配使用。

舉一個例子,例如我們如果要使用count_if演算法來計算容器中大於10的元素的個數。

如果我們使用greater<int>作為判別式(二元),而count_if只接受一個一元判別式,這時候我們就需要搭配函數適配器一起使用了。

而函數指標不能搭配函數適配器一起使用,具體在分析bind2nd的時候會講到。

 1 #include <iostream> 2 #include <vector> 3 #include <functional> 4 #include <algorithm> 5 using namespace std; 6  7  8 int main(int argc, char *argv[]) 9 {10     vector<int> coll{ 1, 3, 5, 7, 9, 11, 13, 15 };11     // 接著下面有bind2nd的具體實現12     cout << count_if(coll.begin(), coll.end(), bind2nd(greater<int>(), 10)) << endl;13     return 0;14 }
View Code

 

bind2nd

bind2nd可以將二元仿函數轉化為一元仿函數,這看上去好像很神奇,其實它的實現很簡單。

首先,二元仿函數會繼承自binary_function,其實只是一些typedef,這些都將用於函數適配器。

 1 template <class Arg1, class Arg2, class Result> 2 struct binary_function { 3     typedef Arg1 first_argument_type; 4     typedef Arg2 second_argument_type; 5     typedef Result result_type; 6 };    7  8 template <class T> 9 struct greater : public binary_function<T, T, bool> {10     bool operator()(const T& x, const T& y) const { return x > y; }11 };
View Code

bind2nd將二元仿函數跟第二個參數型別作為模板型別,下面是具體實現:

 1 template <class Operation, class T> 2 inline binder2nd<Operation> bind2nd(const Operation& op, const T& x) { 3     typedef typename Operation::second_argument_type arg2_type; 4     // 調用binder2nd 5     return binder2nd<Operation>(op, arg2_type(x)); 6 } 7  8 // binder2nd是一個一元仿函數(本身可以搭配函數適配器一起使用) 9 template <class Operation> 10 class binder2nd11   : public unary_function<typename Operation::first_argument_type,12                           typename Operation::result_type> 13 {14 protected:15     // 傳進來的二元仿函數16     Operation op;17     // 傳進來的第二個參數  因為仿函數內部可以typedef  而函數指標則不行18     // 因此只能適配仿函數  而不能適配函數指標19     typename Operation::second_argument_type value;20 public:21     // 建構函式22     binder2nd(const Operation& x,23             const typename Operation::second_argument_type& y) 24        : op(x), value(y) {}25 26     // 直接調用二元仿函數 27     typename Operation::result_type28     operator()(const typename Operation::first_argument_type& x) const {29         return op(x, value); 30     }31 };
View Code

 

STL源碼剖析(仿函數/bind2nd)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.