網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
沒有捕獲任何變量的Lambda表達(dá)式可以轉(zhuǎn)換成與它的調(diào)用原型一致的函數(shù)指針。
參考下面的代碼
void example1()
{
? ? auto add = [](int x, int y)
? ? {
? ? ? ? return x + y;
? ? };
? ? int x = 2, y = 3;
? ? int z1 = add(x, y); ? ? ? ? ? ? ? ? ?// 調(diào)用Lambda
? ? int(*f)(int, int) = add; ? ? ? ? ? ? // Lambda轉(zhuǎn)換成函數(shù)指針
? ? int z2 = f(x, y); ? ? ? ? ? ? ? ? ? ?// 調(diào)用函數(shù)
? ? cout << z1 << ", " << z2 << endl;
}
Lambda是實(shí)現(xiàn)了函數(shù)調(diào)用運(yùn)算符的匿名類(anonymous class)。對(duì)于每一個(gè)Lambda,編譯器創(chuàng)建匿名類,并定義相應(yīng)的數(shù)據(jù)成員存儲(chǔ)Lambda捕獲的變量。沒有捕獲變量的Lambda不包含任何含成員變量。
一個(gè)沒有任何成員變量(包括沒有虛函數(shù)表指針)的類型,在空指針上調(diào)用成員函數(shù)也不會(huì)有任何的問題,因?yàn)樗某蓡T函數(shù)不會(huì)通過this指針訪問內(nèi)存。
當(dāng)Lambda向函數(shù)指針的轉(zhuǎn)換時(shí),編譯器為L(zhǎng)ambda的匿名類實(shí)現(xiàn)函數(shù)指針類型轉(zhuǎn)換運(yùn)算符。
上面的例子中,編譯器實(shí)現(xiàn)operator int(*)(int, int)。
下面是Visual C++編譯器為語(yǔ)句int(*f)(int, int) = add生成的64位匯編代碼:
lea ? ? ? ? rcx,[add] ?
call ? ? ? ?<lambda_0e153cdea67ea404383c23c1022dd325>::operator int (__cdecl*)(int,int)?
mov ? ? ? ? qword ptr [f],rax ?
第1行,變量"add"的地址存入rcx寄存器;第2行,調(diào)用匿名類的函數(shù)指針類型轉(zhuǎn)換運(yùn)算符;第3行,返回結(jié)果存入變量f。
提示:在默認(rèn)的成員函數(shù)調(diào)用約定__thiscall下,this指針通過rcx寄存器傳遞, 有關(guān)__thiscall的詳細(xì)內(nèi)容,請(qǐng)參考:https://docs.microsoft.com/en-us/cpp/cpp/thiscall。
下面是類型轉(zhuǎn)換運(yùn)算符實(shí)現(xiàn)的一行關(guān)鍵匯編代碼
lea ? ? ? ? rax,[<lambda_0e153cdea67ea404383c23c1022dd325>::<lambda_invoker_cdecl>]?
這一行把匿名類的名為lambda_invoker_cdecl的函數(shù)地址存入用于返回結(jié)果的寄存器rax。因?yàn)橹挥蓄惖撵o態(tài)函數(shù)可以轉(zhuǎn)換成非成員函數(shù)指針,所以lambda_invoker_cdecl是靜態(tài)函數(shù)。下面是此函數(shù)其中一段匯編代碼:
xor ? ? ? ? rcx,rcx ?
call ? ? ? ?<lambda_0e153cdea67ea404383c23c1022dd325>::operator()?
第一行,rcx寄存器清0,即this指針置0;第二行,調(diào)用operator()。
綜合上面的分析,得出Lambda轉(zhuǎn)換成函數(shù)指針的一種可能的實(shí)現(xiàn)方式,參考下面的代碼:
typedef int(*FUNCADD)(int, int);
// 實(shí)現(xiàn)兩個(gè)整數(shù)相加的函數(shù)對(duì)象
class add_function_object
{
public:
? ? // 函數(shù)調(diào)用運(yùn)算符
? ? int operator()(int x, int y)const
? ? {
? ? ? ? return x + y;
? ? }
? ? // 函數(shù)指針類型轉(zhuǎn)換運(yùn)算符
? ? operator FUNCADD()const
? ? {
? ? ? ? return add;
? ? }
private:
? ? static int add(int x, int y)
? ? {
? ? ? ? add_function_object* obj = nullptr;
? ? ? ? return obj->operator()(x, y);
? ? }
};
void example2()
{
? ? int x = 2, y = 3;
? ? add_function_object add;
? ? int z1 = add(x, y);
? ? auto fadd = add.operator FUNCADD();
? ? int z2 = fadd(x, y);
? ? cout << z1 << ", " << z2 << endl;
}
從C++17起,沒有捕獲任何變量的Lambda可以用作值類型模板實(shí)參,參考下面的代碼:
typedef int (*INTEGER_OPERATION)(int, int);
int do_integer_operation(INTEGER_OPERATION op, int x, int y)
{
? ? return op(x, y);
}
template <INTEGER_OPERATION op>
int integer_operation_t(int x, int y)
{
? ? return op(x, y);
}
void example3()
{
? ? auto add = [](int x, int y)
? ? {
? ? ? ? return x + y;
? ? };
? ? auto sub = [](int x, int y)
? ? {
? ? ? ? return x - y;
? ? };
? ? int z1 = integer_operation_t<add>(2, 3);
? ? int z2 = do_integer_operation(integer_operation_t<sub>, 2, 3);
? ? cout << "z1 : " << z1 << ", z2 : " << z2 << endl;
}
原文鏈接:https://blog.csdn.net/u011680671/article/details/99660594
相關(guān)推薦
- 2022-04-21 Python的索引與切片原來該這樣理解_python
- 2023-04-27 Redisson分布式限流的實(shí)現(xiàn)原理解析_Redis
- 2022-04-17 uniapp 實(shí)現(xiàn)無感刷新token, 適應(yīng)大多數(shù)項(xiàng)目
- 2022-03-08 使用C語(yǔ)言實(shí)現(xiàn)本地socke通訊的方法_C 語(yǔ)言
- 2022-02-24 詳細(xì)整理Oracle中常用函數(shù)_oracle
- 2022-12-12 python語(yǔ)法之通過value找key問題_python
- 2022-09-25 Django 遷移錯(cuò)誤 Cannot add foreign key constraint,字段類型
- 2022-12-24 python項(xiàng)目運(yùn)行導(dǎo)致內(nèi)存越來越大的原因詳析_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支