Tim的博客

Tim的学习手册

函数对象与谓词

重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象,也叫仿函数(functor),其实就是重载“()”操作符,使得类对象可以像函数那样调用。
注意:
1.函数对象(仿函数)是一个类,不是一个函数。
2.函数对象(仿函数)重载了”() ”操作符使得它可以像函数一样调用。

假定某个类有一个重载的operator(),而且重载的operator()要求获取一个参数,我们就将这个类称为“一元仿函数”(unary functor);相反,如果重载的operator()要求获取两个参数,就将这个类称为“二元仿函数”(binary functor)。
函数对象可以像普通函数那样被调用
函数对象可以像普通函数接受参数

函数对象超出了函数的概念,函数对象保持函数调用的状态

例如:在vector容器中存了几个数据,我们想通过普通函数和函数对象分别打印出这些数据,同时我们想统计一个函数的调用次数,毫无疑问使用函数对象才是最优解!!!

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int num = 0;//统计函数的调用次数,真正开发中,应该尽量避免使用全局变量,因为在多线程中对其加锁解锁过程开销很大!
void MyPrint02(int val){
	cout << val << endl;
	num++;
}

void test(){
	vector<int> v1;
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	for_each(v1.begin(), v1.end(), MyPrint02);
	cout <<"MyPrint02普通函数的调用次数:"<< num << endl;
}

在真正开发中应该尽量避免使用全局变量,能不用则不用,使用全局变量仅仅用来统计函数的执行次数是很不划算的做法,所以函数对象成了我们的最优选择:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//在此处使用struct方便一点,struct与class的区别是struct默认是public的权限
struct MyPrint{
	MyPrint(){
		mNum = 0;
	}
	void operator()(int val){
		cout << val << endl;
		mNum++;
	}
	int mNum; //对象自带的计数器
};

void test(){
	vector<int> v1;
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);

	MyPrint myPrint; //使用函数对象,这样就可以避免使用全局变量
	MyPrint myPrint02 = for_each(v1.begin(), v1.end(), myPrint);
	cout << "myPrint对象的调用次数:" << myPrint.mNum << endl;
}
int main(void){
	test();
	system("pause");
	return 0;
}

接下来说说谓词,谓词是指普通函数或重载的operator()返回值是bool类型的函数对象(仿函数)。如果operator接受一个参数,那么叫做一元谓词,如果接受两个参数,那么叫做二元谓词,谓词可作为一个判断式。

struct myfunc{
      bool operator(int v){}  //接受一个参数,并且返回值为Bool 即一元谓词
}
bool compare01(int v); //同样是叫做一元谓词
struct myfunc{
      bool operator(int v1,int v2){}  //接受两个参数,返回值为Bool 即二元谓词
}
bool compare(int v1,int v2); //同样是叫做二元谓词
一元函数对象 应用举例: for_each
一元谓词 应用举例:find_if
二元函数对象 应用举例: transform

二元谓词 应用举例 : sort

#define _CRT_SECURE_NO_WARNINGS

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>

using namespace std;

//一元函数对象
class print{
public:
	void operator()(const int& v){
		cout << v << " ";
	}
};
void test01(){

	vector<int> v;

	v.push_back(1);
	v.push_back(2);
	v.push_back(5);
	v.push_back(3);

	//一元函数对象
	for_each(v.begin(),v.end(), print());
	cout << endl;

}

//一元谓词
class mygreater{
public:
	bool operator()(const int& v){
		return v > 2;
	}
};
void test02(){
	
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(5);
	v.push_back(3);

	vector<int>::iterator it = find_if(v.begin(), v.end(), mygreater()); //匿名函数对象
	cout << *it << endl;
}

//二元函数对象
class myplus{
public:
	int operator()(int v1,int v2){
		return v1 + v2;
	}
};
void test03(){

	vector<int> v1, v2,v3;
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);

	v2.push_back(7);
	v2.push_back(8);
	v2.push_back(2);


	v3.resize(v1.size()+ v2.size()); // 给v3开辟空间

	transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), myplus());
	for_each(v3.begin(), v3.end(), print());
	cout << endl;
}

//二元谓词
class mycompare{
public:
	bool operator()(int v1,int v2){
		return v1 > v2;
	}
};
void test04(){

	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(5);
	v.push_back(3);

	sort(v.begin(), v.end(), mycompare());
	for_each(v.begin(), v.end(), print());
}

int main(){

	test01();
	test02();
	test03();
	test04();

	system("pause");
	return EXIT_SUCCESS;
}


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38032942/article/details/79967765
上一篇STL容器使用时机总结
下一篇STL内建函数对象
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭