我们在介绍容器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; }