網(wǎng)站首頁 編程語言 正文
先說結(jié)論:
- 對于有捕獲的
lambda
,其等價于對象。 - 對于沒有任何捕獲的
lambda
,其等價于函數(shù)!
首先,很多C++程序員從lambda
用法上反推容易發(fā)現(xiàn)是對象,因為lambda可以捕獲!這是函數(shù)做不到的。的確,比如:
int n = 100; auto foo = [n](int a) { ? ? return a > n; }; cout<< foo(99);
如果編譯器要實現(xiàn)foo
,大致類比這種寫法(可能真實的實現(xiàn)細節(jié)不是這樣,但思路類似)∶
struct Foo { ? ? Foo(int i) {n=i;} ? ? bool operator()(int a) { ? ? ? ? return a > n; ? ? } private: ? ? int n; }; ... int n = 100; Foo foo(n); cout<< foo(99);
如果是引用捕獲了變量,那么struct內(nèi)有一個指針成員持有被引用捕獲的變量的地址。
比如:
set<int> ns = {100, 200, 300}; auto foo = [&ns](int a) { ? ? return ns.find(a); }; cout<< foo(99);
大致等價于:
struct Foo { ? ? Foo(set<int>* p) {p_ns = p;} ? ? bool operator()(int a) { ? ? ? ? auto &ns = *p-ns; ? ? ? ? return ns.find(a); ? ? } private: ? ? set<int>* p_ns; }; ... set<int> ns = {100, 200, 300}; Foo foo(&ns); cout<< foo(99);
然而……這并不是全部!
在沒有捕獲任何東西的時候,lambda
其實是等價于普通的函數(shù)的!可以用Linux C中函數(shù)pthread_create()來驗證!它只能接收一個參數(shù)是void*,返回值也是void*的回調(diào)函數(shù)。
神奇的是,無參的lambda
也可以被pthread_create()
使用!
using namespace std; struct A { ? ? void* operator()(void*) { ? ? ? ? cout<<"xxxx"<<endl; ? ? ? ? return nullptr; ? ? } }; int main() { ? ? A a; ? ? a(NULL); ? ? pthread_t t; ? ? //pthread_create(&t, NULL, a, NULL); // 編譯失敗 ? ? auto cb = [](void*)->void* { ? ? ? ? cout<<"xxxx"<<endl; ? ? ? ? return nullptr; ? ? }; ? ? pthread_create(&t, NULL, cb, NULL); // 編譯通過 ? ? pthread_join(t, NULL); ? ? return 0; }
上面代碼還可以再改一下,讓cb去捕獲一個變量, 比如:
auto cb = [&](void*)->void* { ? ? ? ? cout<<"xxxx"<<endl; ? ? ? ? return nullptr; ? ? }; ? ? pthread_create(&t, NULL, cb, NULL);
這時,給pthread_create()傳入cb同樣會編譯失敗!錯誤信息:
cb.cpp: In function ‘int main()': cb.cpp:23:30: error: cannot convert ‘main()::<lambda(void*)>' to ‘void* (*)(void*)' ? ?23 | ? ? pthread_create(&t, NULL, cb, NULL); ? ? ? | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?^~ ? ? ? | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| ? ? ? | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?main()::<lambda(void*)> In file included from /usr/include/x86_64-linux-gnu/c++/9/bits/gthr-default.h:35, ? ? ? ? ? ? ? ? ?from /usr/include/x86_64-linux-gnu/c++/9/bits/gthr.h:148, ? ? ? ? ? ? ? ? ?from /usr/include/c++/9/ext/atomicity.h:35, ? ? ? ? ? ? ? ? ?from /usr/include/c++/9/bits/ios_base.h:39, ? ? ? ? ? ? ? ? ?from /usr/include/c++/9/ios:42, ? ? ? ? ? ? ? ? ?from /usr/include/c++/9/ostream:38, ? ? ? ? ? ? ? ? ?from /usr/include/c++/9/iostream:39, ? ? ? ? ? ? ? ? ?from cb.cpp:1: /usr/include/pthread.h:200:15: note: ? initializing argument 3 of ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)' ? 200 | ? ? ? void *(*__start_routine) (void *), ? ? ? | ? ? ? ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
這其實也不難理解,C++在lambda的設(shè)計上也貫徹著零開銷 (Zero Overhead)原則,也就是C++不在性能上干多余的事,顯然函數(shù)比對象開銷更小。所以即使同為lambda,在有無捕獲的時候,其底層實現(xiàn)其實是截然不同的!
原文鏈接:https://developer.51cto.com/article/701352.html
相關(guān)推薦
- 2023-01-03 Kotlin文件讀寫與SharedPreferences存儲功能實現(xiàn)方法_Android
- 2022-10-18 shell腳本實現(xiàn)定時刪除文件或文件夾_linux shell
- 2022-09-08 redis?lua限流算法實現(xiàn)示例_Redis
- 2021-11-30 Linux?Autofs自動掛載服務(wù)安裝部署教程_Linux
- 2022-06-04 C++求解二叉樹的下一個結(jié)點問題_C 語言
- 2022-08-29 詳解C語言中二級指針與鏈表的應(yīng)用_C 語言
- 2022-09-30 React前端渲染優(yōu)化--父組件導(dǎo)致子組件重復(fù)渲染的問題_React
- 2022-07-29 Linux中Vi和Vim編輯器用法詳解_linux shell
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支