1. 程式人生 > >【C++】C++之Lambda表示式

【C++】C++之Lambda表示式

作者:李春港 出處:https://www.cnblogs.com/lcgbk/p/14088462.html [toc] # 一、前言 由於前段時間在閱讀一些C++原始碼的時候發現了Lambda表示式,所以在此也記錄下Lambda表示式的使用。 很早之前Lambda在很多高階語言中,就已經被廣泛地使用了,在一個程式中Lambda表示式可以理解為是匿名函式。在C++中,到了C++11標準才引入了這個Lambda表示式,這是C++11最重要而且也是最常用的特性之一。 使用Lambda表示式,不需要額外地定義函式名,可以更直接編寫程式,有比較好的可讀性和可維護性;不需要另外宣告和定義函式體,避免了程式程式碼的膨脹。 # 二、Lambda表示式格式說明 ## 2.1 完整的Lambda表示式格式 ```cpp [capture list] (params list) mutable exception-> return type { function body } ``` 說明: | 名稱 | 解析 | | --- | --- | | [capture list] | 捕獲列表:lambda 表示式可以通過捕獲列表捕獲一定範圍內的變數。 | | (params list) | 形參列表,用於傳參(可以省略)。 | | mutable | 用來說明是否可以修改按值捕獲的變數(可以省略),如果需要修改按值捕獲的變數,則需要新增。 | | exception | 異常設定(可以省略)。 | | return type | 返回型別 (可省略,如果省略則自動從函式體中判斷返回型別,return後的值。如果沒有則返回void)。| | function body | 函式體,即邏輯程式碼。 | ## 2.2 常見的Lambda表示式格式 | 編號 | 格式 | 特性 | | --- | --- | --- | | 格式1 | [capture list] (params list) -> return type {function body} | 1、無法修改捕獲列表中的變數值。 | | 格式2 | [capture list] (params list) {function body} | 1、無法修改捕獲列表中的變數值;2、返回型別由return返回的值型別確定,如果沒有return語句,則返回型別為void。 | | 格式3 | [capture list] {function body} | 1、無法修改捕獲列表中的變數值;2、返回型別由return返回的值型別確定,如果沒有return語句,則返回型別為void;3、不能傳入引數,類似普通的無參函式。 | ## 2.3 lambda 表示式捕獲列表 | 捕獲形式 | 解析 | | --- | --- | | [ ] | 不捕獲任何變數。 | | [&] | 捕獲外部作用域中所有變數,並作為引用在函式體中使用(按引用捕獲)。 | | [=] | 捕獲外部作用域中所有變數,並作為副本在函式體中使用(按值捕獲)。 | |[=,&x] | 按值捕獲外部作用域中所有變數,並按引用捕獲 x 變數。 | | [x] | 按值捕獲 x 變數,同時不捕獲其他變數。 | | [this] | 捕獲當前類中的 this 指標,讓 lambda 表示式擁有和當前類成員函式同樣的訪問許可權。如果已經使用了 & 或者 =,就預設新增此選項。 | **注意:** * 如果是按值捕獲,那麼是否可以改變捕獲的變數值,取決於mutable關鍵字。 # 三、示例 ## 3.1 STL的sort函式引數使用Lambda ```cpp /***************************************************************************** ** Copyright © 2020 lcg. All rights reserved. ** File name: Lambda.cpp ** Description: 在STL的sort函式引數使用Lambda表示式 ** Author: lcg ** Version: 1.0 ** Date: 2020.12.04 *****************************************************************************/ #include #include #include using namespace std; bool cmp(int a, int b) { return a < b; } int main() { vector vec{ 3, 2, 5, 7, 3, 2 }; vector lbvec(vec); /**1、不使用Lambda表示式的寫法**/ sort(vec.begin(), vec.end(), cmp); cout << "predicate function:" << endl; for (int it : vec) // 此for迴圈寫法也是在C++11才出現 cout << it << ' '; cout << endl; /**2、使用Lambda表示式的寫法**/ sort(lbvec.begin(), lbvec.end(), [](int a, int b) ->
bool { return a < b; }); cout << "lambda expression:" << endl; for (int it : lbvec) cout << it << ' '; } ``` 可以看到這種情況使用Lambda表示式可以使程式碼更加直觀、簡介,無需再定義 cmp(int a, int b) 函式。 ## 3.2 有返回值的Lambda表示式 ```cpp /** 1、標明返回型別**/ auto f = [](int a) -> int { return a + 1; }; std::cout << f(1) << std::endl; /**輸出: 2**/ /** 2、無標明返回型別**/ auto f = [](int a) { return a + 1; }; std::cout << f(1) << std::endl; /**輸出: 2**/ ``` 當沒有標明返回型別的時候,系統會根據return回來的值來判斷返回值的型別,auto會自動檢索返回值的型別。 ## 3.3 無引數Lambda表示式 ```cpp auto f = []() { return 1; }; std::cout << f() << std::endl; /**輸出: 1**/ ``` ## 3.4 捕獲外部變數的Lambda表示式 ```cpp /***************************************************************************** ** Copyright © 2020 lcg. All rights reserved. ** File name: Lambda.cpp ** Description: 捕獲外部變數的Lambda表示式 ** Author: lcg ** Version: 1.0 ** Date: 2020.12.04 *****************************************************************************/ #include class A { public: int i_ = 0; void func(int x, int y) { /* error,沒有捕獲外部變數*/ auto x1 = []{ return i_; }; /*OK,按值捕獲所有外部變數,包括了this指標*/ auto x2 = [=]{ return i_ + x + y; }; /*OK,按引用捕獲所有外部變數,包括了this指標*/ auto x3 = [&]{ return i_ + x + y; }; /*OK,捕獲this指標,Lambda擁有和此類中普通函式一樣的許可權*/ auto x4 = [this]{ return i_; }; /*error,沒有捕獲x、y,因為x、y變數不屬於this*/ auto x5 = [this]{ return i_ + x + y; }; /* OK,捕獲this指標、x、y*/ auto x6 = [this, x, y]{ return i_ + x + y; }; /*OK,捕獲this指標,並修改成員的值*/ auto x7 = [this]{ return i_=7; }; x7(); std::cout<