浅析 lambda 表达式
lambda 中的函数调用和普通函数调用有什么区别?
这是一个普通的函数调用
1 | int add(int x, int y){ |
这是一个 lambda 函数调用
1 | void invoke(){ |
下面一起来解开他们的头盖骨,看看下面到底是什么东西。
汇编角度
他们的汇编代码如下, 可以 点击此处查看
查看他们的汇编代码,可以发现 lambda 表达式最后也会被编译成一个函数,调用方式也是常见的函数栈调用,从这个角度来看,lambda 就是一个匿名函数。
但仔细观察,他们还是稍微还是有一点差异,如下
至于为什么会有这样的差异,接下来会讲。
C++ 角度
从 C++ 的角度,解释 lambda 到底是什么,先看下面的示例,下面的代码与上面的 lambda 函数调用代码在汇编代码中等价,点击查看汇编代码
1 | void invoke() |
注意仅仅是在该示例中等价,实际上lambda函数在编译时还会有一个类型转换操作符,用于将lambda对象转换为一个函数指针,本例中没有涉及,故省略。
简单一句话就是编译器会将 lambda 函数编译成一个匿名类, 重载它的 operator ()
方法。
回头来解释上面汇编的几处差异,
1 | invoke()::{lambda(int, int)#1}::operator()(int, int) const: |
lambda参数捕获
拿捕获的变量为 int base=5;
举例。
=
捕获相当于匿名类内部有个 int base;
私有变量。构造函数是 __invoke_add(int &_base): base(_base) {};
&
捕获相当于匿名类内部有个 int &base;
私有变量。构造函数同上。