首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++11 Lambda 表達式入門詳解:語法、捕獲、可變性、轉換與實戰

     編輯:關於C++

Lambda 為什麼有用?

在函數內部快速定義「一次性」可調用對象,無需單獨寫函數/仿函數類。常用於 STL 算法自定義邏輯、多線程回調、延遲計算等場景。

完整語法結構

[捕獲列表] (參數列表) mutable 拋出異常規範 -> 返回類型 { 函數體 }

Lambda語法圖解

捕獲列表 詳解

形式含義
[]不捕獲任何外部變量
[&]**引用捕獲**所有可見自動變量
[=]**值捕獲**所有可見自動變量
[this]捕獲當前對象 this 指針(隱含引用捕獲成員)
[x, &y]值捕獲 x,引用捕獲 y

捕獲規則

  • 默認捕獲模式(= 或 &)與顯式捕獲不能混用同類型:[&, &x] ❌,[=, &x] ✅
  • 同一變量不能重複捕獲:[x, x] ❌,[&x, x] ❌
  • this 只能單獨出現或與默認捕獲組合

參數列表與返回類型

  • 參數列表同普通函數,C++14 支持 auto 泛型參數:[](auto a, auto b){ return a+b; }
  • 返回類型:
    — 單一 return 表達式可自動推導(C++11)
    — 多條 return 或需明確類型時用尾置返回類型:-> int

mutable 說明符

允許修改**值捕獲**的變量(副本):

int n = 0;
auto f = [n](int a) mutable { n += a; cout << n; }; // 編譯通過
f(4); // 輸出 4,外部 n 仍為 0
// 無 mutable 則 n 為 const,無法修改

注意:不影響外部原變量,僅修改閉包內部副本。

Lambda 轉函數指針

**條件**:無捕獲列表([])、非泛型。
轉換後類型:Ret(*)(Params)(非虛、非 explicit、const)。

using Func = void(*)();
Func f = [](){ cout << "hello"; }; // ✅ 無捕獲
// f = [&](){ cout << "hello"; }; // ❌ 有捕獲無法轉換
// VS2010 不支援此轉換,需 VS2012+/GCC 4.8+

實戰案例

1. STL 算法自定義邏輯

vector bs(10);
int val = 0;
generate(bs.begin(), bs.end(), [&val]()->B*{ return new B(++val); });
// 篩選奇數
vector odd;
copy_if(bs.begin(), bs.end(), back_inserter(odd),
        [](B* b){ return b->one % 2; });
// 降序排序
sort(odd.begin(), odd.end(), [](B* a, B* b){ return a->one > b->one; });

2. 多線程回調

Linux/pthread:Lambda 無捕獲可直接轉 void*(*)(void*)

shared_ptr a = make_shared();
pthread_t t;
pthread_create(&t, nullptr, [](void* arg)->void* {
    auto p = static_cast*>(arg);
    cout << (*p)->buf_ << endl;
    delete p;
    return nullptr;
}, new shared_ptr(a));

Windows CreateThread 同理。共享指針 shared_ptr 確保對象存活直到線程結束。

3. 類型擦除存儲任意可調用對象

class Erased {
    struct Base { virtual int call(float)=0; virtual ~Base(){} };
    template struct Derived : Base {
        F f; Derived(F f):f(f) {} int call(float x) override { return f(x); }
    };
    unique_ptr ptr;
public:
    template Erased(F f) : ptr(new Derived(f)) {}
    int operator()(float x) { return ptr->call(x); }
};

Erased e = [i=9](float f) mutable -> int { cout << ++i << endl; return 42; };
e(1.0f); // 輸出 10

總結

  1. Lambda 是**匿名函數對象**,適合局部臨時邏輯
  2. 捕獲列表控制外部變量訪問方式(值/引用),mutable 允許修改值捕獲副本
  3. 無捕獲 Lambda 可隱式轉函數指針,支援 C API 回調
  4. C++14 泛型 Lambda (auto 參數) 大幅提升靈活性
  5. 配合 shared_ptr/unique_ptr 實現安全的跨線程/類型擦除調用
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved