[一文帶你認識 C++ 中的 Lambda 函數](https://mp.weixin.qq.com/s/W_6oaIRVh8qGxye1JzXgww)
閉包
自由變量
* lambda捕獲列表(=傳值、&傳引用、this指針)
```
[&]( int a,int b){
a+b
}
```
*****
> 【導讀】:Lambda函數是?Modern C++在C++11中的一個體現?,雖然在網絡上已經有很多關于lambda函數的討論或者教學,但是仍然有一部分內容(例如IIFE,lambda類型等)沒人談論。因此在這里,我不僅要向您展示C++中的lambda函數,而且還將介紹Lambda的工作原理以及發展。
以下是正文
* * *
**什么是****lambda****函數?**
本文標題有點誤導。因為 lambda并不總是函數指針,它一個表達式。但是為了簡單起見,我一直都稱它為函數。那么在本文中,我將會交替使用lambda函數和表達式來稱呼。
Lambda函數是一段簡短的代碼片段,它具有以下特點:
(1)不值得命名(無名,匿名,可處理等,無論您如何稱呼)
(2)不會重復使用
換句話說,它只是語法糖。lambda函數的語法定義為:
~~~
[ capture list ] (parameters) -> return-type
~~~
通常,?編譯器會評估lambda函數本身的返回類型。因此,我們不需要顯式指定返回類型,即?-> return-type,但是在某些復雜的情況下,編譯器無法推斷出返回類型,此時我們需要指定返回類型。
**為什么要使用****lambda****函數?**
?C++包括許多有用的通用函數,例如 std::for\_each,通常情況下方便了我們的使用。但是,當需要考慮特殊需求的時候,就比較頭疼了。如下代碼所示:
~~~
struct print
~~~
如果您只在某個特定位置使用一次print,卻寫了一個類。這樣的操作代價似乎太大了。
但是,對于這種情況,內聯代碼將更合適,并且可以通過如下的lambda函數來實現:
~~~
std::for_each(v.begin(), v.end(), [](int element) { cout <<element << endl; });
~~~
**lambda****函數工作原理**
~~~
[&i] ( ) { std::cout << i; }
~~~
如代碼所示,編譯器為每一個lambda函數生成獨特的閉合。捕獲列表將成為閉包中的構造函數參數,如果按值捕獲,則會在閉包中創建相應類型的數據成員。此外,您可以在lambda函數參數中聲明變量/對象,它將成為調用運算符的參數,即operator()。
**使用Lambda函數的好處**
(1)零成本抽象。是的! ?你沒看錯。lambda不會犧牲性能,運行速度和普通函數一樣快。
(2)此外,代碼會變得更加緊湊,結構層次更加明顯和代碼可讀性更佳。
**學習****lambda****表達式**
1.通過引用/值捕獲
~~~
int main()
~~~
輸出:
~~~
main()::<lambda()> : 100 , 200
~~~
在上面的示例中,我在捕獲列表中用到了?&。通過引用的方式捕獲變量 x和 y。同樣,=?表示按值捕獲,這將在閉包內創建相同類型的數據成員,同時賦上相同的值。需要注意的是,參數列表是可選的,?如果不將參數傳遞給lambda表達式,則可以省略空括號。
2.Lambda捕獲列表
2.1 將lambda作為參數傳遞
~~~
template <typename Functor>
~~~
輸出:
~~~
Function Type : void f(Functor) [with Functor = main()::<lambda(int)>]
~~~
您也可以將lambda函數作為參數傳遞給其他函數,就像我上面編寫的普通函數一樣。相信您注意到了,我在捕獲列表中聲明了變量i,它將成為數據成員。所以,每次調用lambda\_func時,它將被返回并遞增。
2.2lambda捕獲this指針或成員變量
~~~
class Example
~~~
捕獲this指針也可以使用?\[this\],?\[=\]或者?\[&\]。在上述任何情況下,類內數據成員(包括 private)的訪問方式與常規方法一樣。
可以看到lambda表達式的末尾,我多寫了一個?( ),該函數通常在聲明之后立刻對其進行調用。它稱為IIFE(立即調用函數表達式)。
**C++ lambda****函數類型**
1.通用lambda
~~~
const auto l = [](auto a, auto b, auto c) {};
~~~
C++ 14中引入的通用lambda可以使用auto說明符。
2.可變參數通用λ
~~~
void print() {}
~~~
具有可變參數的Lambda在許多情況下非常有用,例如調試,使用不同的數據輸入重復操作等。
3.mutable lambda函數
通常,lambda的函數調用運算符是const-by-value,這意味著lambda需要捕獲可變值的?關鍵字時,需要使用mutable關鍵字。
~~~
[]() mutable {}
~~~
4.Lambda作為函數指針
~~~
#include<iostream>
~~~
您可以通過添加命令“+”來強制編譯器將lambda生成為函數指針而不是閉包。
5.lambda函數作為返回值
~~~
const auto less_than = [](auto x) {
~~~
再進一步,lambda函數還可以返回另一個lambda函數。這也為代碼的自定義性,代碼可讀性和緊湊性帶來無限可能。
6.constexpr lambda表達式
從C ++ 17開始,可以將lambda表達式聲明為constexpr。
~~~
constexpr auto sum = [](const auto &a, const auto &b) { return a + b; };
~~~
即使你沒有指定?constexpr,如果它恰好滿足所有constexpr函數的要求,那么它也會被聲明為constexpr。
**結束語**
希望您喜歡這篇文章。文中我使用幾個簡單的小例子來介紹關于lambda的大量復雜問題。考慮到代碼的可表達性和易維護性,無論您想到什么,都應該使用lambda,就像可以在自定義刪除器中將其用于智能指針和大多數STL算法一樣。
https://hackernoon.com/all-about-lambda-functions-in-cfrom-c11-to-c17-2t1j32qw
\- EOF -
- C++基礎
- 什么是 POD 數據類型?
- 面向對象三大特性五大原則
- 低耦合高內聚
- C++類型轉換
- c++仿函數
- C++仿函數了解一下?
- C++對象內存模型
- C++11新特性
- 智能指針
- 動手實現C++的智能指針
- C++ 智能指針 shared_ptr 詳解與示例
- 現代 C++:一文讀懂智能指針
- Lamda
- c++11多線程
- std::thread
- std::async
- std::promise
- std::future
- C++11 的內存模型
- 初始化列表
- std::bind
- std::tuple
- auto自動類型推導
- 可變參數模板
- 右值引用與移動語義
- 完美轉發
- 基于范圍的for循環
- C++11之POD類型
- std::enable_if
- C++14/17
- C++20
- 協成
- 模塊
- Ranges
- Boost
- boost::circular_buffer
- 使用Boost.Asio編寫通信程序
- Boost.Asio C++ 網絡編程
- 模板
- 模板特化/偏特化
- C++模板、類模板、函數模板詳解都在這里了
- 泛化之美--C++11可變模版參數的妙用
- 模板元編程
- 這是我見過最好的模板元編程文章!