先來說背景:當我們需要對一些的元素進行排序的時候,可以使用std::sort來進行排序,而當需要對一些自定義類型的元素來排序的時候,要去寫一個類,或者說是需要寫一個仿函數,而如果功能要求上需要根據不同的比較去排序,那就需要寫好幾個仿函數用于去排序,因此這個是很不方便的,比如下面代碼:
struct Goods
{std::string _name; // 名字double _price; // 價格int _evaluate; // 評價Goods(const char* str, double price, int evaluate):_name(str), _price(price), _evaluate(evaluate){}
};
struct ComparePriceLess
{bool operator()(const Goods& gl, const Goods& gr){return gl._price < gr._price;}
};
struct ComparePriceGreater
{bool operator()(const Goods& gl, const Goods& gr){return gl._price > gr._price;}
};
int main()
{std::vector<Goods> v = { { "蘋果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,3 }, { "菠蘿", 1.5, 4 } };std::sort(v.begin(), v.end(), ComparePriceLess());std::sort(v.begin(), v.end(), ComparePriceGreater());
}
因此,lambda表達式可以讓我們免去需要多次寫一個類的這個步驟,下面是使用lambda表達式的例子:
int main()
{std::vector<Goods> v = { {"蘋果",2.1,5},{"香蕉",3,4},{"荔枝",5,6},{"西瓜",1.1,7} };std::sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){return g1._price < g2._price;});std::sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){return g1._price > g2._price;});return 0;
}
lambda表達式語法:
lambda表達式書寫格式:[capture-list] (parameters) mutable -> return-type { statement}
[capture-list]:捕捉列表。該列表總是出現在lambda函數的開始位置,編譯器根據[]來判斷接下來的代碼是否為lambda函數,捕捉列表能夠捕捉上下文中的變量供lambda函數使用。
?
捕捉列表的說明:
?[var] 表示以值傳遞的方式捕捉變量var。
?[=] 表示以值傳遞的方式捕捉父作用域中所有的變量,包括this。父作用域指包含lambda函數的語句塊。
? [&var] 表示以引用傳遞的方式捕捉變量var。
?[&] 表示以引用傳遞的方式捕捉父作用域中所有的變量,包括this。
?[this] 表示捕捉當前的this。
??
說明:
1.語法上捕捉列表可由多個捕捉項組成,并以逗號分割:比如:[=, &a, &b]:以引用傳遞的方式捕捉變量a和b,值傳遞方式捕捉其他所有變量[&,a, this]:值傳遞方式捕捉變量a和this,引用方式捕捉其他變量。
2.捉列表不允許變量重復傳遞,否則就會導致編譯錯誤,比如:比如:[=, a]:=已經以值傳遞方式捕捉了所有變量,捕捉a重復。
3.在塊作用域以外的lambda函數捕捉列表必須為空。
4.lambda表達式之間不能相互賦值,即使看起來類型相同
?
(parameters):參數列表。與普通函數的參數列表一致,如果不需要參數傳遞,則可以連同()一起省略。
?
mutable:默認情況下,lambda函數總是一個const函數,mutable可以取消其常量性。使用該修飾符時,參數列表不可省略(即使參數為空)。
?
->returntype:返回值類型。用追蹤返回類型形式聲明函數的返回值類型,沒有返回值時此部分可省略。返回值類型明確情況下,也可省略,由編譯器對返回類型進行推導。
?
{statement}:函數體。在該函數體內,除了可以使用其參數外,還可以使用所有捕獲
到的變量
在lambda函數定義中,參數列表和返回值類型都是可選部分,而捕捉列表和函數體可以為空。因此C++11中最簡單的lambda函數為:[]{}; 該lambda函數不能做任何事情。
lambda的原理
底層編譯器對于lambda表達式的處理方式,完全就是按照函數對象的方式處理的,即:如果定義了一個lambda表達式,編譯器會自動生成一個類,在該類中重載了operator()。
?