[一文带你认识 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可变模版参数的妙用
- 模板元编程
- 这是我见过最好的模板元编程文章!