当前位置: 首页 > news >正文

c++,从汇编角度看lambda

本篇作为c++,从汇编底层角度深入理解带捕获的lambda如何转化为std::function的开胃小菜

#include <iostream>
#include <functional>int main(int args, char* argv[]) {[](){std::cout << "lambda 0" << std::endl;}();[]() -> int {std::cout << "lambda 1" << std::endl;return 0;}();[](int a = 1) -> int {std::cout << "lambda 1" << std::endl;return a;}();int a = 1, b = 2;[a, b]() -> int {std::cout << b << std::endl;return a;}();
}

编译后看一下符号,lambda相关的只有4个,对应main函数中的4个lambda表达式

# g++ -std=c++20 -fno-elide-constructors  -O0 -g -o main main.cpp
# readelf -s -W main |c++filt |grep lambda13: 0000000000401176    43 FUNC    LOCAL  DEFAULT   14 main::{lambda()#1}::operator()() const14: 00000000004011a2    47 FUNC    LOCAL  DEFAULT   14 main::{lambda()#2}::operator()() const15: 00000000004011d2    48 FUNC    LOCAL  DEFAULT   14 main::{lambda(int)#3}::operator()(int) const16: 0000000000401202    48 FUNC    LOCAL  DEFAULT   14 main::{lambda()#4}::operator()() const

看一下main如何执行这些lambda表达式的:

0000000000401232 <main>:
int main(int args, char* argv[]) {# 申请了 0x20 大小的栈空间401236:	48 83 ec 20          	sub    $0x20,%rsp# lea 是加载地址,调用表达式时`rdi`寄存器传入了一个地址401241:	48 8d 45 f5          	lea    -0xb(%rbp),%rax401245:	48 89 c7             	mov    %rax,%rdi401248:	e8 29 ff ff ff       	call   401176 <main::{lambda()#1}::operator()() const>}();# 看这里和上面的lea加载地址,0xb和0xa,只差1,很奇怪40124d:	48 8d 45 f6          	lea    -0xa(%rbp),%rax401251:	48 89 c7             	mov    %rax,%rdi401254:	e8 49 ff ff ff       	call   4011a2 <main::{lambda()#2}::operator()() const>}();# 第三个 lambda,多传入了 立即数1 作为第二个参数401259:	48 8d 45 f7          	lea    -0x9(%rbp),%rax40125d:	be 01 00 00 00       	mov    $0x1,%esi401262:	48 89 c7             	mov    %rax,%rdi401265:	e8 68 ff ff ff       	call   4011d2 <main::{lambda(int)#3}::operator()(int) const># 第四个,出现差异了int a = 1, b = 2;40127e:	c7 45 fc 01 00 00 00 	movl   $0x1,-0x4(%rbp)401285:	c7 45 f8 02 00 00 00 	movl   $0x2,-0x8(%rbp)# rdi 是 -0x10(%rbp) 地址,这个地址是(a和b共同空间)的地址,只传递了一个地址![a, b]() -> int {40128c:	8b 45 fc             	mov    -0x4(%rbp),%eax40128f:	89 45 f0             	mov    %eax,-0x10(%rbp)401292:	8b 45 f8             	mov    -0x8(%rbp),%eax401295:	89 45 f4             	mov    %eax,-0xc(%rbp)}();401298:	48 8d 45 f0          	lea    -0x10(%rbp),%rax40129c:	48 89 c7             	mov    %rax,%rdi40129f:	e8 6e ff ff ff       	call   401212 <main::{lambda()#4}::operator()() const>

总结:

1、写一个 lambda,就会生成一个对应的函数
2、lambda 的传参,和常规函数传参一致,调用时候传递参数
3、不带捕获的 lambda,第一个参数是一个 无意义的 地址值,类似于类的this,但大小是1,无意义
4、带捕获的lambda,第一个参数是参数列表地址(所有参数排序作为整个空间,传递空间地址,就像传递结构体指针)

http://www.dtcms.com/a/292077.html

相关文章:

  • 查看 iOS iPhone 设备上 App 和系统运行时的实时日志与崩溃日志
  • 十分钟快速完成光伏设计方案
  • C++11特性学习
  • UE5保姆级基础教程(第五章)
  • Linux操作系统之线程(六):线程互斥
  • 金山办公WPS项目产品总监陈智新受邀为第十四届中国PMO大会演讲嘉宾
  • 什么是AI思维:它是智能优先与世界模型重构商业逻辑
  • anchor 智能合约案例6 之 token_lottery
  • 让 Node.js 支持全局路径的模块搜索
  • solidity从入门到精通 第一章:区块链与智能合约的奇妙世界
  • (LeetCode 面试经典 150 题 ) 128. 最长连续序列 (哈希表)
  • 【bug】 jetson上opencv无法录制h264本地视频
  • [Dify] -进阶9- 使用 API 调用方式将 Dify 嵌入自己的网站
  • Typecho三种版权保护方法对比与实战指南
  • 【硬件基础】计算机存储和通信领域名词概念解释,时钟频率,传输速率,总线宽度,存储容量,带宽利用率,数据位宽,数据带宽
  • 牛客:最长无重复子数组
  • 嵌入式开发学习———Linux环境下数据结构学习(一)
  • Web3面试题
  • [特殊字符] 字节内部流出版!19道前端核心面试题解析——速存
  • 网络基础16--VRRP技术
  • ospf技术
  • 中国在远程医疗智能化方面有哪些特色发展模式?
  • js 数字逢三切断、整数最大9位、小数最大2位
  • LeetCode 热题100:42.接雨水
  • 数据交换---JSON格式
  • uniapp在app中关于解决输入框键盘弹出后遮住输入框问题
  • haproxy七层均衡
  • ucharts 搭配uniapp 自定义x轴文字 实现截取显示
  • 基于SpringBoot+Uniapp的非遗文化宣传小程序(AI问答、协同过滤算法、Echarts图形化分析)
  • 代码随想录算法训练营Day35|动态规划Part03|01背包问题 二维、01背包问题 一维、416. 分割等和子集