Lambda 表达式完整的格式如下:

[捕获列表] (形参列表) mutable 异常列表-> 返回类型
{
函数体
}

各项的含义:

  • 捕获列表:捕获外部变量,捕获的变量可以在函数体中使用,可以省略,即不捕获外部变量。
  • 形参列表:和普通函数的形参列表一样。可省略,即无参数列表
  • mutable:mutable 关键字,如果有,则表示在函数体中可以修改捕获变量,根据具体需求决定是否需要省略。
  • 异常列表:noexcept / throw(...),和普通函数的异常列表一样,可省略,即代表可能抛出任何类型的异常。
  • 返回类型:和函数的返回类型一样。可省略,如省略,编译器将自动推导返回类型。
  • 函数体:代码实现。可省略,但是没意义。

示例:

void LambdaDemo()
{
int a = 1;
int b = 2;
auto lambda = [a, b](int x, int y)mutable throw() -> bool
{
return a + b > x + y;
};
bool ret = lambda(3, 4);
}

对应的汇编代码如下:

LambdaDemo()::{lambda(int, int)#1}::operator()(int, int):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov DWORD PTR [rbp-12], esi
mov DWORD PTR [rbp-16], edx
mov rax, QWORD PTR [rbp-8]
mov edx, DWORD PTR [rax]
mov rax, QWORD PTR [rbp-8]
mov eax, DWORD PTR [rax+4]
lea ecx, [rdx+rax]
mov edx, DWORD PTR [rbp-12]
mov eax, DWORD PTR [rbp-16]
add eax, edx
cmp ecx, eax
setg al
pop rbp
ret
LambdaDemo():
push rbp
mov rbp, rsp
sub rsp, 32
mov DWORD PTR [rbp-4], 1
mov DWORD PTR [rbp-8], 2
mov eax, DWORD PTR [rbp-4]
mov DWORD PTR [rbp-20], eax
mov eax, DWORD PTR [rbp-8]
mov DWORD PTR [rbp-16], eax
lea rax, [rbp-20]
mov edx, 4
mov esi, 3
mov rdi, rax
call LambdaDemo()::{lambda(int, int)#1}::operator()(int, int)
mov BYTE PTR [rbp-9], al
nop
leave
ret

可见,在调用匿名函数时,直接调用了LambdaDemo()::{lambda(int, int)#1}::operator()方法,这也体现出lambda匿名函数的优势

  • 1、内联优化:Lambda表达式可以被编译器更好地内联优化。由于lambda通常在定义时使用,编译器可以获取更多的上下文信息,从而进行更有效的优化。(能够在需要使用的时候定义,并且无需跳出当前函数)

  • 2、减少函数调用的开销:相比于传统函数,匿名函数可以减少函数调用的开销,因为它们不需要通过函数指针调用,并且可以避免在调用栈上创建额外的帧。

  • 3、泛型编程:C++14引入了泛型lambda表达式,它允许编写更通用的代码,减少了模板特化的需要,这样不仅可以提高代码的可读性,还可以减少编译器生成的代码量,从而可能提高性能。

PS:函数调用汇编代码:



可以看出,在用函数调用来实现上述lambda匿名函数相同的功能时,因未能获取更多的上下文信息,就需要传入更多的参数来实现该功能,从而影响性能

可使用:https://godbolt.org/ 查看对应代码的汇编

编译器原理

编译器实现 lambda 表达式大致分为一下几个步骤

  • 1、创建 lambda 类,实现构造函数,使用 lambda 表达式的函数体重载 operator()(所以 lambda 表达式 也叫匿名函数对象)
  • 2、创建 lambda 对象
  • 3、通过对象调用 operator()
class lambda_xxxx
{
private:
int a;
int b;
public:
lambda_xxxx(int _a, int _b) :a(_a), b(_b)
{
}
bool operator()(int x, int y) throw()
{
return a + b > x + y;
}
};
void LambdaDemo()
{
int a = 1;
int b = 2;
lambda_xxxx lambda = lambda_xxxx(a, b);
bool ret = lambda.operator()(3, 4);
}

其中,类名 lambda_xxxx 的 xxxx 是为了防止命名冲突加上的。

lambda_xxxx 与 lambda 表达式 的对应关系

  • lambda 表达式中的捕获列表,对应 lambda_xxxx 类的private 成员
  • lambda 表达式中的形参列表,对应 lambda_xxxx 类成员函数 operator() 的形参列表
  • lambda 表达式中的mutable,对应 lambda_xxxx 类 成员函数operator()的常属性 const,即是否是常成员函数
  • lambda 表达式中的返回类型,对应 lambda_xxxx 类成员函数 operator() 的返回类型
  • lambda 表达式中的函数体,对应 lambda_xxxx 类成员函数 operator() 的函数体

另外,lambda 表达 捕获列表的捕获方式,也影响 对应 lambda_xxxx 类的 private 成员 的类型

  • 值捕获:private 成员 的类型与捕获变量的类型一致
  • 引用捕获:private 成员 的类型是捕获变量的引用类型

注:

如果该匿名函数未用mutable关键词修饰,如下:

auto func1 = [](){cout << "hello world!" << endl; };
func1();

对应的类:(着重关注operator()的定义,属性)

template<typename T=void>
class TestLambda01
{
public:
TestLambda01() {}
void operator()()const
{
cout << "hello world!" << endl;
}
};

operator()它是const的 哦^_ ^

C++ lambda匿名函数的更多相关文章

  1. lambda匿名函数透析

    lambda匿名函数透析 目录 1       匿名函数的作用... 1 2       匿名函数的格式... 1 3       匿名函数实例代码... 3   1         匿名函数的作用 ...

  2. lambda 匿名函数

    # 普通python函数 def func(a,b,c): return a+b+c print func(1,2,3) # 返回值为6 # lambda匿名函数 f = lambda a,b,c:a ...

  3. lambda 形参:返回值 lambda 匿名函数 格式:

    lambda 匿名函数 格式: lambda 形参:返回值 e.g f = lambda n:n**2 print(f(10))

  4. Python 进阶 之 lambda 匿名函数

    lambda 是个匿名函数,通常用于简单判断或者处理,例如判断一个数的奇偶性,过滤字符串,逻辑运算等等. lambda表达式: >>>lambda x:x*x >>> ...

  5. xpinyin-函数返回多个值-lambda匿名函数-列表生成式-三元表达式

    import xpinyinp=xpinyin.Pinyin() #实例化print(p.get_pinyin('小白','')) 函数返回多个值:1.函数如果返回多个值的话,它会把这几个值放到一个元 ...

  6. lambda匿名函数和他的小伙伴(处理大量数据的时候用到)

    lambda匿名函数 主要是为了解决一些简单的需求而设计的一句话函数 #计算n的n次方 def func(n): return n**n f = lambda n : n ** n 语法: 函数名 = ...

  7. lambda匿名函数,sorted(),filter(),map(),递归函数

    1.lambda匿名函数 为了解决一些简单的需求而设计的一句话函数 #计算n的n次方 def func(n): return n**n print(func(10)) f = lambda n: n* ...

  8. python基础-4 函数参数引用、lambda 匿名函数、内置函数、处理文件

    上节课总结 1.三元运算 name=“name1”if 条件 else “name2” 2.深浅拷贝 数字.字符串 深浅,都一样 2.其他 浅拷贝:只拷贝第一层 深拷贝:不拷贝最后一层 3.set集合 ...

  9. Python 之父为什么嫌弃 lambda 匿名函数?

    Python 支持 lambda 匿名函数,其扩展的 BNF 表示法是lambda_expr ::= "lambda" [parameter_list] ":" ...

  10. Java中的lambda匿名函数使用

    Java中的lambda匿名函数使用 lambda匿名函数的使用是为了满足某些情况下需要临时定义函数,或者事先定义,需要时才使用.在python里面,lambda表达式的表达方式为:lambda 参数 ...

随机推荐

  1. Vue实现企业微信扫码登录

        Vue实现企业微信扫码登录   企业微信扫码登录原理 构建企业微信登录二维码 获取访问令牌access_token 请求方式:GET(HTTPS)请求URL:https://qyapi.wei ...

  2. Typecho博客服务器搬家换空间方法教程

    Typecho 博客搬家方法步骤: 1.备份Typecho博客数据库,进入到phpmyadmin选择自己博客的数据表进行导出备份 2.使用FTP(或者登陆空间控制面板)把所有的Typecho文件下载到 ...

  3. HTTP - [01] 简介

    HTTP本身是不安全的,因为传输的数据未经加密,可能会被窃听或篡改.为了解决这个问题,引入了HTTPS,即在HTTP上加入SSL/TLS协议,为数据传输提供了加密和身份验证. 一.概述   HTTP( ...

  4. 在Vue 3中创建和使用FormData对象

    在Vue 3中创建和使用FormData对象的具体步骤如下‌: ‌创建FormData对象‌:在Vue组件中,首先需要创建一个新的FormData对象.FormData是一个内置的JavaScript ...

  5. 05_模块(import & from)

    模块(import & from) 导入模块 在和.py同级文件夹下创建一个自定义的模块 fibo.py def fib_return(x): a, b = 0, 1 result = [] ...

  6. 关于Mysql触发器的使用

    当我在回复表新增数据 我就会执行下列语句 触发器在mysql的使用过DELIMITER $$开头 END; $$ 结尾,注意 触发的语句必须用:结尾 创建触发器DELIMITER $$CREATE T ...

  7. Ollama系列02:快速上手搭建私有的AI对话框和智能体—chatbox版

    本文是Ollama系列教程的第2篇,在上一篇中我们介绍了Ollama的安装.大模型的下载和本地部署,本篇中我们将介绍如何将Ollama整合到chatBox中,并构建属于自己的智能体. Ollama系列 ...

  8. composer 指定php版本

    需要指定php和composer的位置,然后再去执行composer命令 ## 指定PHP版本 指定composer 指定载入包 /usr/local/php7/bin/php composer /u ...

  9. http://eslint.org/docs/rules/semi

    报错: Errors: 88 http://eslint.org/docs/rules/semi 56 http://eslint.org/docs/rules/quotes 34 http://es ...

  10. Python 潮流周刊#94:如何解决 FastAPI 的大文件传输问题?(摘要)

    本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...