C++——STL标准模板库——函数对象

一、基本概念

函数对象也叫仿函数,是通过一个类封装了()的重载函数,该类实例化对象就叫做函数对象。这意味着函数可以被赋值给变量,可以作为参数传递给其他函数,也可以作为返回值从函数中返回。主要用于算法的自定义行为或者回调函数等。

函数对象不仅封装了()的重载函数,还可以定义自身的成员属性用来实现更复杂的目的。

二、谓词

返回值为bool类型的()重载函数对象叫做谓词。参数列表中只需接收一个参数的叫做一元谓词,接收两个参数的叫做二元谓词。C++STL中很多算法参数列表中显示需要一个名字叫_Pred的东西,大多数情况下就是需要一个谓词。

class GreatFive {							//一元谓词
public:
	bool operator()(int value) {
		return value > 5;
	}
};
void test() {
	vector<int> v{ 1,2,3,4,5,6,7,8,9 };
	auto it = find_if(v.begin(), v.end(), GreatFive());
	cout << *it << endl;
}

代码中GreatFive就是一元谓词,it返回指向第一个大于5的元素的迭代器 。

template<class C>
void printC(const C& c) {
	for (typename C::const_iterator it = c.begin(); it != c.end(); it++) {
		cout << (*it) << " ";
	}
	cout << endl;
}

class MyCompare {							//二元谓词
public:
	bool operator()(int v1,int v2) {
		return v1 > v2;
	}
};
void test() {
	vector<int> v{ 1,3,2,5,4 };
	sort(v.begin(), v.end());
	printC(v);
	sort(v.begin(), v.end(), MyCompare());
	printC(v);
}

代码中MyCompare就是二元谓词,sort算法默认递增排序,通过MyCompare实现递减排序

三、内建函数对象

STL中提供了多种内置的函数对象,用来实现内置数据类型的基础运算、关系比较以及逻辑与、或、非,在使用内建函数时需要:#include <functional>

(一)算术仿函数

template<class T> T pluse<T>        //加法仿函数

template<class T> T minus<T>       //减法仿函数

template<class T> T multiplies<T>  //乘法仿函数

template<class T> T divides<T>      //除法仿函数

template<class T> T  modulus<T>   //取模仿函数

template<class T> T negate<T>       //取反仿函数

除了取反是一元运算,其他函数对象都是二元运算

//for_each是STL提供的遍历算法,可以自定义遍历过程中的功能,需要包含algorithm,
//需要提供一个只接收一个参数的函数。

//transform函数时STL提供的复制算法,将一个容器的元素逐一复制到另一个容器,
//过程中可以自定义处理功能,需要提供一个只接收一个参数的函数,并返回该参数类型。
//所以不能直接使用modulus的()重载

void print(int&a) {											//为for_each遍历算法提供输出功能函数
	cout << a << " ";
}
int ModulusBy5(int &a) {									//为transform复制算法提供数据处置功能
	return modulus<int>()(a, 5);							//modulus仿函数
}
void test() {
	vector<int> v{ 1,2,3,4,5,6,7,8,9 };
	vector<int> v1;
	v1.resize(v.size());									//复制前需要开辟相应的空间

	for_each(v.begin(), v.end(), print); cout << endl;		//遍历v容器
	transform(v.begin(), v.end(), v1.begin(), ModulusBy5);	//将[v.begin(),v.end())内的元素逐一经过ModulusBy5处理,复制到v1
	for_each(v1.begin(),v1.end(), print);					//遍历v1容器
}

(二)关系仿函数

template<class T> bool equal_to<T>                 //等于

template<class T> bool not_equal_to<T>          //不等于

template<class T> bool greater<T>                   //大于

template<class T> bool greater_equal<T>        //大于等于

template<class T> bool less<T>                        //小于

template<class T> bool less_equal<T>             //小于等于

//sort算法是STL提供的排序算法模板函数,默认递增排序,源码中默认使用二元谓词less<>()
//当容器中存储的是自定义类型或者内置类型递减排序时需要提供其他的排序函数对象(二元谓词)
//greater<T> 是STL提供的递减排序的二元谓词
void print(int&a) {
	cout << a << " ";
}

void test() {
	vector<int>v({ 4,2,5,3,1,7,6 });
	sort(v.begin(), v.end());
	for_each(v.begin(), v.end(), print); cout << endl;
	sort(v.begin(), v.end(), greater<int>());
	for_each(v.begin(), v.end(), print); cout << endl;
}

(三)逻辑仿函数

template<class T> bool logical_and<T>;                逻辑与

template<class T> bool logical_or<T>;                   逻辑或

template<class T> bool logcial_not<T>;                  逻辑非

//利用transform将v中的bool类型经过func的处理复制到d中
//使用逻辑非内建函数对象

bool func(const bool& b) {
	return  logical_not<bool>()(b);
}
template<class T>
void print(const T& b) {
	cout << b << " ";
}
void test() {
	vector<bool>v{ true,false,true,false,true,false };
	deque<bool>d;
	d.resize(v.size());
	for_each(v.begin(), v.end(), print<bool>); cout << endl;
	transform(v.begin(), v.end(), d.begin(), func);
	for_each(d.begin(), d.end(), print<bool>);
}