NO IMAGE

我們在介紹容器set的時候就涉及到了函式物件這個概念,本節就是在原來的基礎之上,系統深入的談一談STL中的函式物件。


  • 函式物件的基本概念

    • 函式物件本質上是一個類而不是一個函式
    • 函式物件過載了運算子(),從而使物件能夠像函式一樣的被呼叫
  • 函式物件與普通函式的對比

    • 函式物件超出了普通函式的功能,能夠儲存函式呼叫狀態(如果使用全域性變數儲存函式呼叫次數,要給程式加鎖,解鎖。所以不推薦使用全域性變數;而函式物件則能夠很好的解決該問題。)

      
      #include <iostream>
      using namespace std;
      class compare{
      public:
      int cnt = 0;    //可以記錄函式呼叫次數
      bool operator()(int i, int j){
      this->cnt  ;
      return i > j;
      }
      };
      bool compare_fun(int i, int j){
      return i > j;
      }
      int main(){
      compare a, b;
      cout<<a(1, 2)<<" "<<compare_fun(1,2)<<endl;
      cout << b(4, 3) << " " << compare_fun(2, 1) << endl;
      a(3, 4);
      a(5, 6);
      a(7, 8);
      cout << "函式物件a呼叫次數: " << a.cnt << " " << "函式物件b呼叫次數: " <<b.cnt << endl;
      return 0;
      }
    • 函式物件可以做引數,做返回值
      利用for_each實現列印容器vector中的所有元素

      
      #include <iostream>
      #include <vector>
      #include <algorithm>
      using namespace std;
      class print{
      public:
      int cnt = 0;
      void operator()(int i){
      cout << i << " ";
      cnt  ;
      }
      };
      int main(){
      vector<int> v;
      for (int i = 0; i < 10; i  ){
      v.push_back(i); 
      }
      print p1;
      p1=for_each(v.begin(), v.end(), p1); //函式物件做函式引數和函式返回值,這是普通函式無法實現的
      cout << endl;
      cout << p1.cnt << endl;
      return 0;
      }

  • STL中預定義的函式物件
    STL中的函式物件都封裝在functional標頭檔案中。

    下面以plus為例子,講解一下STL封裝的函式物件如何使用。

    
    #include <iostream>
    #include <vector>
    #include <string>
    #include <functional>
    #include <algorithm>
    using namespace std;
    int main(){
    plus<int> plus_int;
    int ret = plus_int(10, 20);
    cout << ret << endl;
    plus<string> plus_str;
    string a = "aaa";
    string b = "bbb";
    string c = plus_str(a, b);
    cout << c << endl;
    cout << plus<int>()(1, 2) << endl;  //匿名物件
    return 0;
    }

  • 一元函式物件,二元函式物件,一元謂詞,二元謂詞
    函式物件接收一個引數,稱為一元函式物件;函式物件接收兩個引數,則稱為二元函式物件。
    函式物件或者普通函式接收一個引數,並且返回值是bool資料型別,稱為一元謂詞;函式物件或者普通函式接收兩個引數,並且返回值是bool資料型別,則稱為二元謂詞。
    我們下面以for_each(),find_if(),transform()和sort為例子,分別講解一元函式物件,一元謂詞,二元函式物件,二元謂詞。

    
    #include <iostream>
    #include <vector>
    #include <string>
    #include <functional>
    #include <algorithm>
    using namespace std;
    template<class T>
    class print{
    public:
    int ret = 0;
    void operator()(T i){
    cout << i << " ";
    ret  ;
    }
    };
    class compare{
    public:
    bool operator()(int i){
    return i > 7;
    }
    };
    class sort_int{
    public:
    bool operator()(int v1, int v2){
    return v1 > v2;
    }
    };
    void test01(){
    //一元函式物件 for_each
    vector<int> v;
    for (int i = 0; i < 100; i  ){
    v.push_back(i   1);
    }
    print<int> print_int;
    print_int = for_each(v.begin(), v.end(), print_int);
    cout << endl;
    cout << print_int.ret << endl;
    }
    void test02(){
    //一元謂詞  find_if
    vector<int> v;
    v.push_back(1);
    v.push_back(7);
    v.push_back(8);
    vector<int>::iterator i = find_if(v.begin(), v.end(), compare());
    if (i == v.end()){
    cout << "cannot find!!!" << endl;
    }
    else{
    cout << "find : " << *i << endl;
    }
    }
    void test03(){
    //transform() 對兩個容器進行操作,將結果存放在第三個容器中
    vector<int> v1,v2,v3;
    for (int i = 0; i < 10; i  ){
    v1.push_back(i);
    v2.push_back(i   1);
    }
    //v3在transform之前要先開闢記憶體空間
    v3.resize(100);
    transform(v1.begin(),v1.end(),v2.begin(),v3.begin(),plus<int>());
    for (int i = 0; i < v3.size(); i  ){
    cout << v3.at(i) << " ";
    }
    cout << endl;
    }
    void test04(){
    //二元謂詞 sort
    vector<int> v1;
    v1.push_back(3);
    v1.push_back(2);
    v1.push_back(9);
    v1.push_back(6);
    for_each(v1.begin(), v1.end(), print<int>());
    cout << endl;
    sort(v1.begin(), v1.end(), sort_int());
    for_each(v1.begin(), v1.end(), print<int>()); cout << endl;
    }
    int main(){
    test01();
    test02();
    test03();
    test04();
    return 0;
    }