STL之函数对象和谓词
1.函數(shù)對象
重載函數(shù)調(diào)用操作符的類,其對象常稱為函數(shù)對象(function object),即它們是行為類似函數(shù)的對象。一個類對象,表現(xiàn)出一個函數(shù)的特征,就是通過“對象名+(參數(shù)列表)”的方式使用一個類對象,如果沒有上下文,完全可以把它看作一個函數(shù)對待。
這是通過重載類的operator()來實現(xiàn)的。
“在標準庫中,函數(shù)對象被廣泛地使用以獲得彈性”,標準庫中的很多算法都可以使用函數(shù)對象或者函數(shù)來作為自定的回調(diào)行為;
一元函數(shù)對象:函數(shù)參數(shù)1個;
二元函數(shù)對象:函數(shù)參數(shù)2個;
2.謂詞
一元謂詞: 函數(shù)參數(shù)1個,函數(shù)返回值是bool類型,可以作為一個判斷式
二元謂詞: 函數(shù)參數(shù)2個,函數(shù)返回值是bool類型
謂詞可以使一個仿函數(shù),也可以是一個回調(diào)函數(shù)。
一元謂詞舉例如下:
1.判斷給出的string對象的長度是否小于6
2.判斷給出的int是否在3到8之間
bool Compare( int i ) { return ( i >= 3 && i <= 8 ); }二元謂詞舉例如下:
1.比較兩個string對象,返回一個bool值,指出第一個string是否比第二個短
3.一元函數(shù)對象案例
//1普通類 重載 函數(shù)調(diào)用操作符 template <typename T> void FuncShowElemt(T &t) //普通函數(shù) 不能像 仿函數(shù)那樣記錄狀態(tài) {cout << t << " "; };void showChar(char &t) {cout << t << " "; }//函數(shù)模板 重載 函數(shù)調(diào)用操作符 template <typename T> class ShowElemt { public:ShowElemt(){n = 0;}void operator()(T &t){n++;cout << t << " ";}void printCount(){cout << n << endl;} public:int n; };//1 函數(shù)對象 基本使用 void main11() {int a = 100;FuncShowElemt<int>(a); //普通的函數(shù)調(diào)用ShowElemt<int> showElemt; //函數(shù)對象 showElemt(a); //函數(shù)對象調(diào)用 }4.一元謂詞案例
//1元謂詞 例子 template <typename T> class Isdiv { public:Isdiv(const T &divisor) //{this->divisor = divisor;}bool operator()(T &t){return (t%divisor == 0);} protected: private:T divisor; };void main13() {vector<int> v2;for (int i=10; i<33; i++){v2.push_back(i);}vector<int>::iterator it;int a = 4;Isdiv<int> mydiv(a);// _InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred) //返回的是迭代器it = find_if(v2.begin(), v2.end(), Isdiv<int>(4));if (it != v2.end()){cout << "第一個被4整除的數(shù)是:" << *it << endl;} }5.二元函數(shù)對象案例
template <typename T> struct SumAdd {T operator()(T &t1, T &t2){return t1 + t2;} };template <typename T> void printE(T &t) {for (vector<int>::iterator it = t.begin(); it!=t.end(); it++ ){cout << *it << " ";} }void printVector(vector<int> &v) {for (vector<int>::iterator it = v.begin(); it!=v.end(); it++ ){cout << *it << " ";} }void main14() {vector<int> v1, v2 ;vector<int> v3;v1.push_back(1);v1.push_back(2);v1.push_back(3);v2.push_back(4);v2.push_back(5);v2.push_back(6);v3.resize(10);//transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), SumAdd<int>());/*template<class _InIt1,class _InIt2,class _OutIt,class _Fn2> inline_OutIt transform(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _OutIt _Dest, _Fn2 _Func)*/vector<int>::iterator it = transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), SumAdd<int>());cout << *it << endl;printE(v3); }6.二元謂詞案例
void current(int &v) {cout << v << " "; }bool MyCompare(const int &a, const int &b) {return a < b; } void main15() {vector<int> v(10);for (int i=0; i<10; i++){v[i] = rand() % 100;}for_each(v.begin(), v.end(), current);printf("\n");sort(v.begin(), v.end(), MyCompare );printf("\n");for (int i=0; i<10; i++){printf("%d ", v[i]);}printf("\n"); }7.綜合示例代碼
#include <iostream> using namespace std;#include "string" #include <vector> #include <list> #include "set" #include <algorithm> #include "functional"//函數(shù)對象 類重載了() template <typename T> class ShowElemt { public:ShowElemt(){n = 0;}void operator()(T &t){n ++;//printN();cout << t << " ";}void printN(){cout << "n:" << n << endl;} protected: private:int n; };//函數(shù)模板 ==函數(shù) template <typename T> void FuncShowElemt(T &t) {cout << t << endl; }//普通函數(shù) void FuncShowElemt2(int &t) {cout << t << " "; }//函數(shù)對象 定義 ; 函數(shù)對象和普通函數(shù)的異同 // void main01() {int a = 10;ShowElemt<int> showElemt;showElemt(a); //函數(shù)對象的()的執(zhí)行 很像一個函數(shù) //仿函數(shù)FuncShowElemt<int>(a);FuncShowElemt2(a); }//函數(shù)對象是屬于類對象,能突破函數(shù)的概念,能保持調(diào)用狀態(tài)信息 //函數(shù)對象的好處 // for_each算法中, 函數(shù)對象做函數(shù)參數(shù) // for_each算法中, 函數(shù)對象當返回值 void main02() {vector<int> v1;v1.push_back(1);v1.push_back(3);v1.push_back(5);for_each(v1.begin(), v1.end(), ShowElemt<int>()); //匿名函數(shù)對象 匿名仿函數(shù)cout << endl;for_each(v1.begin(), v1.end(), FuncShowElemt2); //通過回調(diào)函數(shù) 誰使用for_each 誰去填寫回調(diào)函數(shù)的入口地址ShowElemt<int> show1;//函數(shù)對象 做函數(shù)參數(shù) /*template<class _InIt,class _Fn1> inline_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func){ // perform function for each element_DEBUG_RANGE(_First, _Last);_DEBUG_POINTER(_Func);return (_For_each(_Unchecked(_First), _Unchecked(_Last), _Func));}*///1 for_each算法的 函數(shù)對象的傳遞 是元素值傳遞 ,不是引用傳遞for_each(v1.begin(), v1.end(), show1);show1.printN();cout << "通過for_each算法的返回值看調(diào)用的次數(shù)" << endl;show1 = for_each(v1.begin(), v1.end(), show1);show1.printN();//結(jié)論 要點: 分清楚 stl算法返回的值是迭代器 還是 謂詞(函數(shù)對象) 是stl算法入門的重要點 }template<typename T> class IsDiv { public:IsDiv(const T &divisor){this->divisor = divisor;}bool operator()(T &t){return (t%divisor == 0);}protected: private:T divisor; };void main03() {vector<int> v2;for (int i=10; i<33; i++){v2.push_back(i);}int a = 4;IsDiv<int> myDiv(a);//find_if(v2.begin(), v2.end(), myDiv );/*template<class _InIt,class _Pr> inline_InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred){ // find first satisfying _Pred_DEBUG_RANGE(_First, _Last);_DEBUG_POINTER(_Pred);return (_Rechecked(_First,_Find_if(_Unchecked(_First), _Unchecked(_Last), _Pred)));}//find_if返回值是一個迭代器 //要點: 分清楚 stl算法返回的值是迭代器 還是 謂詞(函數(shù)對象) 是stl算法入門的重要點*/vector<int>::iterator it;it = find_if(v2.begin(), v2.end(), IsDiv<int>(a) );if (it == v2.end()){cout << "容器中沒有被4整除的元素" << endl;}else{cout <<"第一個是被4整除的元素是:" << *it << endl;}}//二元函數(shù)對象 template <typename T> class SumAdd { public:T operator()(T t1, T t2){return t1 + t2;} };void main04() {//v1 v2 ==> v3vector<int> v1, v2;vector<int> v3;v1.push_back(1);v1.push_back(3);v1.push_back(5);v2.push_back(2);v2.push_back(4);v2.push_back(6);v3.resize(10);/*template<class _InIt1,class _InIt2,class _OutIt,class _Fn2> inline_OutIt transform(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _OutIt _Dest, _Fn2 _Func){ // transform [_First1, _Last1) and [_First2, ...) with _Func_DEBUG_RANGE(_First1, _Last1);_DEBUG_POINTER(_Dest);_DEBUG_POINTER(_Func);if (_First1 != _Last1)return (_Transform2(_Unchecked(_First1), _Unchecked(_Last1),_First2, _Dest, _Func,_Is_checked(_Dest)));return (_Dest);}//transform 把運算結(jié)果的 迭代器的開始位置 返回出來 */transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), SumAdd<int>() );for (vector<int>::iterator it=v3.begin(); it!=v3.end(); it++ ){cout << *it << " ";}cout << endl; }bool MyCompare(const int &a, const int &b) {return a < b; //從小到大 }void main05() {vector<int> v1(10);for (int i=0; i<10; i++){int tmp = rand() %100;v1[i] = tmp;}for (vector<int>::iterator it=v1.begin(); it!=v1.end(); it++ ){cout << *it <<" ";}cout << endl;for_each(v1.begin(), v1.end(), FuncShowElemt2);cout << endl;sort(v1.begin(), v1.end(), MyCompare);for_each(v1.begin(), v1.end(), FuncShowElemt2);cout << endl; }struct CompareNoCase {bool operator()(const string &str1, const string &str2){string str1_ ;str1_.resize(str1.size() );transform(str1.begin(), str1.end(), str1_.begin(), tolower ); //預(yù)定義函數(shù)對象 string str2_ ;str2_.resize(str2.size() );transform(str2.begin(), str2.end(), str2_.begin(), tolower ); //預(yù)定義函數(shù)對象 return (str1_ < str2_); // 從小到大進行排序} }; void main06() {set<string> set1;set1.insert("bbb");set1.insert("aaa");set1.insert("ccc");set<string>::iterator it = set1.find("aAa"); //find函數(shù) 默認 區(qū)分大小寫if (it == set1.end()){cout << " 沒有 查找到 aaa " << endl;}else{cout << " 查找到 aaa " << endl;}set<string, CompareNoCase> set2;set2.insert("bbb");set2.insert("aaa");set2.insert("ccc");set<string, CompareNoCase>::iterator it2 = set2.find("aAa");if (it2 == set2.end()){cout << " 沒有 查找到 aaa " << endl;}else{cout << " 不區(qū)分大小的的查找 查找到 aaa " << endl;}}void main1111() {//main01(); //函數(shù)對象基本概念//main02(); //函數(shù)對象的好處 函數(shù)對象做函數(shù)參數(shù) 函數(shù)對象做返回值//main03(); //一元謂詞//main04(); //二元函數(shù)對象 和二元謂詞//main05(); //二元函數(shù)對象 和二元謂詞main06(); //二元謂詞在set集合中的應(yīng)用cout<<"hello..."<<endl;system("pause");return ; }8.預(yù)定義函數(shù)對象
標準模板庫STL提前定義了很多預(yù)定義函數(shù)對象,#include <functional> 必須包含。
//1使用預(yù)定義函數(shù)對象: //類模板plus<> 實現(xiàn)了: 不同類型的數(shù)據(jù)進行加法運算 void main41() {plus<int> intAdd;int x = 10;int y = 20;int z = intAdd(x, y); //等價于 x + y cout << z << endl;plus<string> stringAdd;string myc = stringAdd("aaa", "bbb");cout << myc << endl;vector<string> v1;v1.push_back("bbb");v1.push_back("aaa");v1.push_back("ccc");v1.push_back("zzzz");//缺省情況下,sort()用底層元素類型的小于操作符以升序排列容器的元素。//為了降序,可以傳遞預(yù)定義的類模板greater,它調(diào)用底層元素類型的大于操作符:cout << "sort()函數(shù)排序" << endl;;sort(v1.begin(), v1.end(), greater<string>() ); //從大到小for (vector<string>::iterator it=v1.begin(); it!=v1.end(); it++ ){cout << *it << endl;} }8.1算術(shù)函數(shù)對象
預(yù)定義的函數(shù)對象支持加、減、乘、除、求余和取反。調(diào)用的操作符是與type相關(guān)聯(lián)的實例
//加法:plus<Types> plus<string> stringAdd; sres = stringAdd(sva1,sva2);減法:minus<Types> 乘法:multiplies<Types> 除法divides<Tpye> 求余:modulus<Tpye> 取反:negate<Type> negate<int> intNegate; ires = intNegate(ires); Ires= UnaryFunc(negate<int>(),Ival1);8.2關(guān)系函數(shù)對象
等于equal_to<Tpye> equal_to<string> stringEqual; sres = stringEqual(sval1,sval2); 不等于not_equal_to<Type> 大于 greater<Type> 大于等于greater_equal<Type> 小于 less<Type> 小于等于less_equal<Type> void main42() {vector<string> v1;v1.push_back("bbb");v1.push_back("aaa");v1.push_back("ccc");v1.push_back("zzzz");v1.push_back("ccc");string s1 = "ccc";//int num = count_if(v1.begin(),v1.end(), equal_to<string>(),s1);int num = count_if(v1.begin(),v1.end(),bind2nd(equal_to<string>(), s1));cout << num << endl; }8.3邏輯函數(shù)對象
邏輯與 logical_and<Type> logical_and<int> indAnd; ires = intAnd(ival1,ival2); dres=BinaryFunc( logical_and<double>(),dval1,dval2); 邏輯或logical_or<Type> 邏輯非logical_not<Type> logical_not<int> IntNot; Ires = IntNot(ival1); Dres=UnaryFunc( logical_not<double>,dval1);總結(jié)
以上是生活随笔為你收集整理的STL之函数对象和谓词的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 反编译工具的使用和字节码文件的查看(Bi
- 下一篇: 面试基础-- JDK、JRE、JVM