做者:李春港
出處:http://www.javashuo.com/article/p-otyliogr-nx.htmlhtml
因爲前段時間在閱讀一些C++源碼的時候發現了Lambda表達式,因此在此也記錄下Lambda表達式的使用。ios
很早以前Lambda在不少高級語言中,就已經被普遍地使用了,在一個程序中Lambda表達式能夠理解爲是匿名函數。在C++中,到了C++11標準才引入了這個Lambda表達式,這是C++11最重要並且也是最經常使用的特性之一。express
使用Lambda表達式,不須要額外地定義函數名,能夠更直接編寫程序,有比較好的可讀性和可維護性;不須要另外聲明和定義函數體,避免了程序代碼的膨脹。函數
[capture list] (params list) mutable exception-> return type { function body }
說明:this
名稱 | 解析 |
---|---|
[capture list] | 捕獲列表:lambda 表達式能夠經過捕獲列表捕獲必定範圍內的變量。 |
(params list) | 形參列表,用於傳參(能夠省略)。 |
mutable | 用來講明是否能夠修改按值捕獲的變量(能夠省略),若是須要修改按值捕獲的變量,則須要添加。 |
exception | 異常設定(能夠省略)。 |
return type | 返回類型 (可省略,若是省略則自動從函數體中判斷返回類型,return後的值。若是沒有則返回void)。 |
function body | 函數體,即邏輯代碼。 |
編號 | 格式 | 特性 |
---|---|---|
格式1 | [capture list] (params list) -> return type {function body} | 一、沒法修改捕獲列表中的變量值。 |
格式2 | [capture list] (params list) {function body} | 一、沒法修改捕獲列表中的變量值;二、返回類型由return返回的值類型肯定,若是沒有return語句,則返回類型爲void。 |
格式3 | [capture list] {function body} | 一、沒法修改捕獲列表中的變量值;二、返回類型由return返回的值類型肯定,若是沒有return語句,則返回類型爲void;三、不能傳入參數,相似普通的無參函數。 |
捕獲形式 | 解析 |
---|---|
[ ] | 不捕獲任何變量。 |
[&] | 捕獲外部做用域中全部變量,並做爲引用在函數體中使用(按引用捕獲)。 |
[=] | 捕獲外部做用域中全部變量,並做爲副本在函數體中使用(按值捕獲)。 |
[=,&x] | 按值捕獲外部做用域中全部變量,並按引用捕獲 x 變量。 |
[x] | 按值捕獲 x 變量,同時不捕獲其餘變量。 |
[this] | 捕獲當前類中的 this 指針,讓 lambda 表達式擁有和當前類成員函數一樣的訪問權限。若是已經使用了 & 或者 =,就默認添加此選項。 |
注意:spa
/***************************************************************************** ** Copyright © 2020 lcg. All rights reserved. ** File name: Lambda.cpp ** Description: 在STL的sort函數參數使用Lambda表達式 ** Author: lcg ** Version: 1.0 ** Date: 2020.12.04 *****************************************************************************/ #include <iostream> #include <vector> #include <algorithm> using namespace std; bool cmp(int a, int b) { return a < b; } int main() { vector<int> vec{ 3, 2, 5, 7, 3, 2 }; vector<int> lbvec(vec); /**一、不使用Lambda表達式的寫法**/ sort(vec.begin(), vec.end(), cmp); cout << "predicate function:" << endl; for (int it : vec) // 此for循環寫法也是在C++11纔出現 cout << it << ' '; cout << endl; /**二、使用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) 函數。指針
/** 一、標明返回類型**/ auto f = [](int a) -> int { return a + 1; }; std::cout << f(1) << std::endl; /**輸出: 2**/ /** 二、無標明返回類型**/ auto f = [](int a) { return a + 1; }; std::cout << f(1) << std::endl; /**輸出: 2**/
當沒有標明返回類型的時候,系統會根據return回來的值來判斷返回值的類型,auto會自動檢索返回值的類型。code
auto f = []() { return 1; }; std::cout << f() << std::endl; /**輸出: 1**/
/***************************************************************************** ** Copyright © 2020 lcg. All rights reserved. ** File name: Lambda.cpp ** Description: 捕獲外部變量的Lambda表達式 ** Author: lcg ** Version: 1.0 ** Date: 2020.12.04 *****************************************************************************/ #include <iostream> 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<<i_<<std::endl;//輸出7 /*OK,捕獲全部外部變量,默認捕獲this指針,並修改爲員的值*/ auto x8 = [=]{ return i_=8; }; x8(); std::cout<<i_<<std::endl;//輸出8 /*error,由於i_不屬於捕獲範圍的變量,因此沒法按值捕獲i_變量,能夠經過捕獲this指針來獲取i_使用權*/ auto x9 = [i_]{ return i_++; }; /*error,緣由同上*/ auto x10 = [&i_]{ return i_++; }; /*ok,按引用捕獲全部變量,默認捕獲this指針,並修改爲員的值*/ auto x11 = [&]{ return i_=11; }; x11(); std::cout<<i_<<std::endl;//輸出11 /*error,按值捕獲x變量,並修改值*/ auto x12 = [x]{ return x++; }; /*ok,按值捕獲x變量,並修改值*/ auto x13 = [x]()mutable{ return x=13; }; x13(); std::cout<<x<<std::endl;//輸出1 /*ok,按引用捕獲x變量,並修改值*/ auto x14 = [&x]{ return x=14; }; x14(); std::cout<<x<<std::endl;//輸出14 } }; int main(int argc, char *argv[]) { A l; l.func(1,2); int a = 0, b = 1; /*error,沒有捕獲外部變量*/ auto f1 = []{ return a; }; /*OK,捕獲全部外部變量,改變a值*/ auto f2 = [&]{ return a=2; }; f2(); std::cout<<a<<std::endl;//輸出2 /*OK,捕獲全部外部變量,並返回a*/ auto f3 = [=]{ return a; }; /*error,a是以複製方式捕獲的,沒法修改*/ auto f4 = [=]{ return a=4; }; /*ok,a是以複製方式捕獲的,修改a值*/ auto f4 = [=]()mutable{ return a=4; }; f4(); std::cout<<a<<std::endl;//輸出2 /*error,沒有捕獲變量b*/ auto f5 = [a]{ return a + b; }; /*OK,捕獲a和b的引用,並對b作自加運算*/ auto f6 = [a, &b]{ return a + (b++); }; /*OK,捕獲全部外部變量和b的引用,並對b作自加運算*/ auto f7 = [=, &b]{ return a + (b++); }; return 0; }
總結:htm