引子
lambda表达式的本质是什么呢?为探究这个问题,我们将一段写有lambda表达式的代码反编译,可能会发现一些秘密.
首先写段程序:
//#include...
auto flambda = [](int x,int y)->int{return x + y;};
int main()
{
cout<<flambda(3,2)<<endl;
return 0;
}
在调试该代码时我们打开汇编视图,发现如下代码:
callq 0x100000d80 <$_0::operator()(int, int) const> mov 0x2c4(%rip),%rdi # 0x100001010 mov %eax,%esi
其中 <$_0::operator()(int, int) const> 即对应原代码中的lambda表达式。这里一串重载了"()"(operator())操作符的代码,即本文将要了解的仿函数。
Note: 此处的 const ,也应证了前文 mutable 可变范围 中提到的,lambda的调用运算符为"const-by-value"的
定义
仿函数(finctor)是一种早期的叫法,在C++11中,标准的叫法为函数对象(function object)。仿函数是一种行为类似函数、具有函数特性的对象。
仿函数是一个对象,而不是函数。仿函数的类通过重载函数操作符"()"(operator())来实现函数调用的特性。
通过下面的例子来简单说明如何使用仿函数
#include <functional>
//#include...
class myGreater
{
public:
bool operator()(int x,int y) //重载调用操作函数
{return x>y;}
};
int main()
{
greater<int> gt; //lineA
cout<<boolalpha<<gt(4,3)<<endl; //lineB
cout<<greater<int>()(3,4)<<endl; //lineC
cout<<myGreater()(5,3)<<endl; //lineD
return 0;
}
//OUTPUT:
//true
//false
//true
这个例子中,lineA声明了一个对象。这是一个函数对象,其类(结构)定义在functional文件中,是STL内置的模板类。该类用于比较两个参数的大小。
lineB则像函数一样直接给该对象传入两个参数。
lineC是另一种写法。greater<int>() 声明了一个临时对象,然后传入参数(3,4)调用该临时对象。这种写法往往比lineB更加简洁。在STL源码里大量使用了这种写法。
lineD则是使用自定义的函数对象。
Note:lineB中使用了boolalpha,是iostream提供的一个操作符,这将使此后的标准输出中,将bool值输出为"true"或"false",而不是1/0。于其相反的操作为noboolalpha.
