新聞中心
關(guān)于C++的lambda是函數(shù)還是對象,這其實(shí)不是一個(gè)一概而論的問題。

你所需要的網(wǎng)站建設(shè)服務(wù),我們均能行業(yè)靠前的水平為你提供.標(biāo)準(zhǔn)是產(chǎn)品質(zhì)量的保證,主要從事網(wǎng)站設(shè)計(jì)、做網(wǎng)站、企業(yè)網(wǎng)站建設(shè)、手機(jī)網(wǎng)站制作設(shè)計(jì)、網(wǎng)頁設(shè)計(jì)、成都品牌網(wǎng)站建設(shè)、網(wǎng)頁制作、做網(wǎng)站、建網(wǎng)站。創(chuàng)新互聯(lián)公司擁有實(shí)力堅(jiān)強(qiáng)的技術(shù)研發(fā)團(tuán)隊(duì)及素養(yǎng)的視覺設(shè)計(jì)專才。
先說結(jié)論:
- 對于有捕獲的lambda,其等價(jià)于對象。
- 對于沒有任何捕獲的lambda,其等價(jià)于函數(shù)!
首先,很多C++程序員從lambda 用法上反推容易發(fā)現(xiàn)是對象,因?yàn)閘ambda可以捕獲!這是函數(shù)做不到的。的確,比如:
int n = 100;
auto foo = [n](int a) {
return a > n;
};
cout<< foo(99);
如果編譯器要實(shí)現(xiàn)foo,大致類比這種寫法(可能真實(shí)的實(shí)現(xiàn)細(xì)節(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)有一個(gè)指針成員持有被引用捕獲的變量的地址。
比如:
setns = {100, 200, 300};
auto foo = [&ns](int a) {
return ns.find(a);
};
cout<< foo(99);
大致等價(jià)于:
struct Foo {
Foo(set* p) {p_ns = p;}
bool operator()(int a) {
auto &ns = *p-ns;
return ns.find(a);
}
private:
set* p_ns;
};
...
set ns = {100, 200, 300};
Foo foo(&ns);
cout<< foo(99);
然而……這并不是全部!
在沒有捕獲任何東西的時(shí)候,lambda其實(shí)是等價(jià)于普通的函數(shù)的!可以用Linux C中函數(shù)pthread_create()來驗(yàn)證!它只能接收一個(gè)參數(shù)是void*,返回值也是void*的回調(diào)函數(shù)。
神奇的是,無參的lambda也可以被pthread_create()使用!
#include
#include
using namespace std;
struct A {
void* operator()(void*) {
cout<<"xxxx"<return nullptr;
}
};
int main() {
A a;
a(NULL);
pthread_t t;
//pthread_create(&t, NULL, a, NULL); // 編譯失敗
auto cb = [](void*)->void* {
cout<<"xxxx"<return nullptr;
};
pthread_create(&t, NULL, cb, NULL); // 編譯通過
pthread_join(t, NULL);
return 0;
}
上面代碼還可以再改一下,讓cb去捕獲一個(gè)變量, 比如:
auto cb = [&](void*)->void* {
cout<<"xxxx"< return nullptr;
};
pthread_create(&t, NULL, cb, NULL);
這時(shí),給pthread_create()傳入cb同樣會編譯失?。″e誤信息:
cb.cpp: In function ‘int main()’:
cb.cpp:23:30: error: cannot convert ‘main()::’ to ‘void* (*)(void*)’
23 | pthread_create(&t, NULL, cb, NULL);
| ^~
| |
| main()::
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 *),
| ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
這其實(shí)也不難理解,C++在lambda的設(shè)計(jì)上也貫徹著零開銷 (Zero Overhead)原則,也就是C++不在性能上干多余的事,顯然函數(shù)比對象開銷更小。所以即使同為lambda,在有無捕獲的時(shí)候,其底層實(shí)現(xiàn)其實(shí)是截然不同的!
名稱欄目:C++的lambda是函數(shù)還是對象?
網(wǎng)頁網(wǎng)址:http://m.fisionsoft.com.cn/article/cdogdep.html


咨詢
建站咨詢
