謂詞、內建函數對象、函數對象適配器

1、謂詞概念

謂詞是指普通函數或重載的operator()返回值是bool類型的函數對象(仿函數)。若是operator接收一個參數,那麼叫作一元謂詞,若是接收兩個參數,那麼叫作二元謂詞,謂詞可做爲一個判斷式。ios

2、內建函數對象

STL內建了一些函數對象,分爲:算數類函數對象,關係運算類函數對象,邏輯運算類仿函數。這些仿函數所產生的對象,用法和通常函數徹底相同,固然咱們還能夠產生無名的臨時對象來履行函數功能,使用內建函數對象,須要引入頭文件#include<functional>算法

6個算數類函數對象,除了negate是一元運算,其餘都是二元運算。函數

6個關係運算類函數對象,每一種都是二元運算。字體

邏輯運算類仿函數,not爲一元運算,其他爲二元運算。spa

案例(以plus爲例):指針

#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <functional>
using namespace std; void test01() { //使用內建函數對象聲明一個對象
    plus<int> myplus; cout << myplus(10, 20) << endl;//30 //使用匿名臨時對象
    cout << plus<int>()(5, 6) << endl;//11
} int main(void) { test01(); return 0; }

3、函數對象適配器

函數對象適配器是完成一些配接工做,這些配接包括綁定(bind),否認(negate),以及一對通常函數或成員函數的修飾,使其成爲函數對象,重點掌握函數對象適配器(紅色字體):code

bind1st:將參數綁定爲函數對象的第一個參數對象

bind2nd:將參數綁定爲函數對象的第二個參數blog

not1:對一元函數對象取反排序

not2:對二元函數對象取反

ptr_fun:將普通函數修飾成函數對象

mem_fun:修飾成員函數

mem_fun_ref:修飾成員函數

一、綁定適配器:bind1st、bind2nd

bind1st和bind2nd函數把一個二元函數對象綁定成爲一個一元函數對象。可是因爲二元函數對象接受兩個參數,在綁定成爲一元函數對象時須要將原來兩個參數中的一個綁定下來。也即經過綁定二元函數對象的一個參數使之成爲一元函數對象的。bind1st是綁定第一個參數,bind2nd則是綁定第二個參數。

#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <vector> #include <algorithm> #include <functional>
using namespace std; struct MyPrint:public binary_function<int,int,void> { void operator()(int v, int val) const { cout << v + val << " "; cout << "v:" << v << " val:" << val << endl; } }; //仿函數適配器 bind1st bind2nd 綁定適配器
void test01() { vector<int> v; for (int i = 0;i < 10;i++) { v.push_back(i); } int addNum = 200; //綁定適配器 將一個二元函數對象轉變成一元函數對象
 for_each(v.begin(), v.end(), bind1st(MyPrint(), addNum)); /* 200 v:200 val:0 201 v:200 val:1 202 v:200 val:2 203 v:200 val:3 204 v:200 val:4 205 v:200 val:5 206 v:200 val:6 207 v:200 val:7 208 v:200 val:8 209 v:200 val:9 */ for_each(v.begin(), v.end(), bind2nd(MyPrint(), addNum)); /* 200 v:0 val:200 201 v:1 val:200 202 v:2 val:200 203 v:3 val:200 204 v:4 val:200 205 v:5 val:200 206 v:6 val:200 207 v:7 val:200 208 v:8 val:200 209 v:9 val:200 */

    //由此可得bind1st與bind2nd的區別: //bind1st 將addNum綁定爲函數對象的第一個參數; //bind2nd 將addNum綁定爲函數對象的第二個參數
} int main(void) { test01(); return 0; }

二、取反適配器:not1和not2

not1是構造一個與謂詞結果相反的一元函數對象,not2是構造一個與謂詞結果相反的二元函數對象。
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <vector> #include <algorithm> #include <functional>
using namespace std; struct MyCompare :public binary_function<int, int, bool> { //由大到小比較
    bool operator()(int v1,int v2) const { return v1 > v2; } }; struct MyPrint02 { void operator()(int v) { cout << v << " "; } }; struct MyGreater5:public unary_function<int,bool> { //第一個大於5的數
    bool operator()(int v) const { return v > 5; } }; //仿函數適配器 not1 not2 取反適配器
void test02() { vector<int> v; for (int i = 9;i > -1;i--) { v.push_back(i); } for_each(v.begin(), v.end(), MyPrint02()); cout << endl;//9 8 7 6 5 4 3 2 1 0
    sort(v.begin(), v.end(), not2(MyCompare()));//由小到大排序
    for_each(v.begin(), v.end(), MyPrint02());//0 1 2 3 4 5 6 7 8 9
    cout << endl; //not1 not2 區別 //若是對一元謂詞取反,用not1; //若是對二元謂詞取反,用not2;
 vector<int>::iterator it = find_if(v.begin(), v.end(), not1(MyGreater5()));//第一個小於等於5的值
    if (it == v.end()) { cout << "沒有找到!" << endl; } else { cout << *it << endl;//0
 } } int main(void) { test02(); return 0; }

三、函數對象適配器:ptr_fun

 ptr_fun是將一個普通的函數適配成一個仿函數(functor)

#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <vector> #include <algorithm> #include <functional>
using namespace std; //仿函數適配器 ptr_fun
void MyPrint03(int val1,int val2)//普通函數MyPrint03 { cout << val1 + val2 << " "; cout << "val1:" << val1 << " val2:" << val2 << endl; } void test03() { vector<int> v; for (int i = 0;i < 10;i++) { v.push_back(i); } //ptr_fun:把普通函數 轉成 函數對象
    for_each(v.begin(), v.end(), bind1st(ptr_fun(MyPrint03),10)); /* 10 val1:10 val2:0 11 val1:10 val2:1 12 val1:10 val2:2 13 val1:10 val2:3 14 val1:10 val2:4 15 val1:10 val2:5 16 val1:10 val2:6 17 val1:10 val2:7 18 val1:10 val2:8 19 val1:10 val2:9 */ } int main(void) { test03(); return 0; }

四、成員函數適配器:mem_fun、mem_fun_ref

mem_fun_ref的做用和用法跟mem_fun同樣,惟一的不一樣就是:當容器中存放的是對象實體的時候用mem_fun_ref,當容器中存放的是對象的指針的時候用mem_fun

#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <vector> #include <algorithm> #include <functional>
using namespace std; void test04() { //若是容器中存放的對象或者對象指針,for_each算法打印的時候,調用類本身提供的打印函數
    vector<Person> v; Person p1(10, 20), p2(30, 40), p3(50, 60); v.push_back(p1); v.push_back(p2); v.push_back(p3); //mem_fun_ref 格式:&類名::函數名
    for_each(v.begin(), v.end(), mem_fun_ref(&Person::show)); /* age:10 id:20 age:30 id:40 age:50 id:60 */ cout << "-------------" << endl; vector<Person*> v1; v1.push_back(&p1); v1.push_back(&p2); v1.push_back(&p3); for_each(v1.begin(), v1.end(), mem_fun(&Person::show)); /* age:10 id:20 age:30 id:40 age:50 id:60 */

    //mem_fun_ref mem_fun 區別? //若是存放的是對象指針 使用mem_fun //若是存放的是對象 使用mem_fun_ref
} int main(void) { test04(); return 0; }
相關文章
相關標籤/搜索