亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

蟲蟲首頁| 資源下載| 資源專輯| 精品軟件
登錄| 注冊

您現在的位置是:首頁 > 技術閱讀 >  C++的lambda是函數還是對象?

C++的lambda是函數還是對象?

時間:2024-02-10

關于C++的lambda是函數還是對象,這其實不是一個一概而論的問題。

先說結論:

  • 對于有捕獲的lambda,其等價于對象。
  • 對于沒有任何捕獲的lambda,其等價于函數!

首先,很多C++程序員從lambda 用法上反推容易發現是對象,因為lambda可以捕獲!這是函數做不到的。的確,比如:

int n = 100;
auto foo = [n](int a) {
    return a > n;
};
cout<< foo(99);

如果編譯器要實現foo,大致類比這種寫法(可能真實的實現細節不是這樣,但思路類似)∶

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內有一個指針成員持有被引用捕獲的變量的地址。

比如:

set<int> ns = {100200300};
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 = {100200300};
Foo foo(&ns);
cout<< foo(99);

然而……這并不是全部!

在沒有捕獲任何東西的時候,lambda其實是等價于普通的函數的!可以用Linux C中函數pthread_create()來驗證!它只能接收一個參數是void*,返回值也是void*的回調函數。

神奇的是,無參的lambda也可以被pthread_create()使用!

#include <iostream>
#include <pthread.h>
using namespace std;

struct A {

    voidoperator()(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的設計上也貫徹著零開銷 (Zero Overhead)原則,也就是C++不在性能上干多余的事,顯然函數比對象開銷更小。所以即使同為lambda,在有無捕獲的時候,其底層實現其實是截然不同的!


深入理解glibc malloc:內存分配器實現原理


為什么空類大小是1


C/C++為什么要專門設計個do…while?


推薦一個學習技術的好網站


Linux最大并發數是多少?


累夠嗆!整理了一份C++學習路線圖!


主站蜘蛛池模板: 米泉市| 丹巴县| 翁源县| 报价| 澜沧| 四川省| 贵德县| 瓦房店市| 宝清县| 龙陵县| 万荣县| 化隆| 大田县| 交口县| 宁明县| 朔州市| 鱼台县| 翁源县| 乐昌市| 彰化县| 宁河县| 福清市| 神池县| 汶上县| 五华县| 陇西县| 秦皇岛市| 桃园市| 武功县| 天镇县| 枣阳市| 遂宁市| 溆浦县| 宁化县| 临澧县| 鸡东县| 哈密市| 溧水县| 兖州市| 神农架林区| 中阳县|