好的编程语言一般都有好的库支持,C++也是如此。C++语言在标准程序库STL中向用户提供了一些基本的数据结构和一些基本的算法。C++11之前,我们在使用STL算法时,通常会使用一些特别的对象,称之为函数对象或者仿函数。
仿函数就是重新定义了成员函数operator()的一种自定义对象。这样的函数有个特点,就是其使用在代码层感觉根函数的使用并无二样,但其本质并非函数。比如:
class _functor{
public:
int operator()(int x, int y){ return x + y}
};
int main(){
_functor total;
return total(1, 3);
}
上面的total并不是函数名称,而是对象名称。
相比于函数,仿函数可以拥有初始状态,一般通过class定义私有成员,并在声明对象的时候对其进行初始化。私有成员的状态就成了仿函数的初始状态。而由于声明一个仿函数对象可以拥有多个不同的初始状态的实例,因此可以借由防函数产生多个功能类似缺不同的仿函数实例:
#include <iostream>
class Tax{
private:
float rate;
int base;
public:
Tax(float r, int b) : rate(r), base(b){}
float operator()(float money) { return (money - base) * rate;}
};
int main(){
Tax high(0.4, 3000);
Tax middle(0.25, 2000);
std::cout << high(35722) << "," << middle(25723);
}
那么lambda函数和仿函数有什么关系呢?
#include <iostream>
class AirportPrice{
private:
float _dutyfreerate;
public:
AirportPrice(float rate) : _dutyfreerate(rate){}
float operator()(float price){
return price * (1 - _dutyfreerate);
}
};
int main(){
float tax_rate = 5.5f;
AirportPrice changi(tax_rate);
auto changi2 = [tax_rate](float price)->float{ return price * (1 - tax_rate / 100);};
auto purchaes = changi(3699);
auto prucha2 = changi2(2899);
}
从上面可以看出,lambda函数捕捉了tax_rate变量,而仿函数以tax_rate初始化类。可以看到,出去语法层面上的不同,lamda函数与仿函数有相同的内涵:都可以捕捉一些变量作为初始状态,并接受参数进行运算。
实际上,仿函数是编译器实现lambda的一种方式。在现阶段,通常编译器会把lamda函数转化成一个仿函数对象。因此,lamda可以视为仿函数的语法糖
实际使用时,可以使用lamdad来代替仿函数来书写代码。