STL -函数对象
函数对象
重载函数调用操作符的类,其对象常称为函数对象,即他们是行为类似函数的对象,也叫仿函数,其实就是重载”()”操作符,使得类对象可以像函数一样调用。
Note
- 函数对象是一个类,不是一个函数
- 函数对象(仿函数)重载了”()” 操作符使得它可以像函数一样调用
分类:假定某个类有一个重载的operator(),而且重载的operator()要求获取一个参数,我们就将这个类称为”一元仿函数”(unary functior),相反,如果重载的operator()要求获取两个参数,就将这个类称为”二元仿函数”(binary functor)
作用
STL提供的算法往往都有两个版本,其中一个版本表现出最常用的某种运算,另一个版本则是允许用户通过template参数的形式来指定所要采取的策略。
代码例子
/*************************************************************************
> File Name: main.cpp
> Author: 仿函数的使用方法
> Mail:
> Created Time: 2019年12月31日 星期二 16时09分25秒
************************************************************************/
# include<iostream>
using namespace std;
class MyPrint
{
public:
void operator()(int num)
{
cout<<"Here "<<count++<<" is MyPrint:"<<num<<endl;
}
private:
int count=0; //保存内部状态
};
//函数对象作为参数
void test01()
{
cout<<"test01"<<endl;
MyPrint myPrint;
myPrint(10);
myPrint(10);
myPrint(10);
myPrint(10);
}
void doPrint(MyPrint print,int num)
{
cout<<"doPrint:";
print(num);
}
int main()
{
test01();
MyPrint()(1234); //匿名对象的调用方式
doPrint(MyPrint(),1001); //传递匿名对象
return 0;
}
总结
- 函数对象通常不定义构造函数和析构函数,所以在构造和析构时不会发生任何问题,避免了函数调用的运行时问题。
- 函数对象超出了普通函数的概念,函数对象可以有自己的状态
- 函数对象可内联编译,性能好,用函数指针几乎不可能
- 模板函数对象使函数对象具有通用性,这也是它的优势之一。
谓词
谓词就是返回值为bool的普通函数或者是仿函数,根据参数的个数也有一元谓词和二元谓词.
示例代码
/*************************************************************************
> File Name: main.cpp
> Author:
> Mail:
> Created Time: 2019年12月31日 星期二 16时29分35秒
************************************************************************/
# include<iostream>
# include <vector>
# include <algorithm>
using namespace std;
//一元谓词
class GreaterThen20{
public :bool operator()(const int & val)
{
return val>20;
}
};
void test01()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
//查找第一个大于20的数字
if(find_if(v.begin(),v.end(),GreaterThen20())!=v.end());
cout<<"找到了"<<endl;
}
//二元谓词
class MyCompare{
public :
bool operator()(const int &v1,const int &v2)
{ return v1>v2; }
};
void test02()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
sort(v.begin(),v.end(),MyCompare());
//匿名函数 lambda表达式 [](){}
for_each(v.begin(),v.end(),[](int val){cout<<val<<" ";});
}
int main()
{
test01();
test02();
return 0;
}
内建函数对象
STL内建了一些函数对象,分为算术类函数对象,关系运算类函数对象,逻辑运算类仿函数。这些仿函数所产生的对象,用发货一般函数完全相同,当然我们还可以产生无名的临时对象来履行函数功能。使用内建函数对象需要引入头文件# include
6个算术类函数对象,除了negate是一元运算,其他都是二元运算
template<class T> T plus<T> //加法仿函数
template<class T> T minius<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> //取反仿函数
6个关系运算类函数对象,每一种都是二元谓词
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> //小于等于
逻辑运算类运算函数,not为一元谓词,其余都是二元谓词
template<class T> bool logical_and<T> //逻辑与
template<class T> bool logical_ro<T> //逻辑或
template<class T> bool logical_not<T> //逻辑非
代码示例
/*************************************************************************
> File Name: main.cpp
> Author: 内建函数对象
> Mail:
> Created Time: 2019年12月31日 星期二 16时46分37秒
************************************************************************/
# include <vector>
# include<iostream>
# include <functional>
# include <algorithm>
using namespace std;
void test01()
{
negate<int> n; //取反
cout<<"negate:"<<n(10)<<endl;
plus<int> p;
cout<<"plus: "<<p(1,1)<<endl;
}
void test02()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
sort(v.begin(),v.end(),greater<int>());
for_each(v.begin(),v.end(),[](int val){cout<<val<<" ";});
}
int main()
{
test01();
test02();
return 0;
}
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment