C++ Lambda 表达式介绍


author: hjjdebug
date: 2025年 05月 16日 星期五 09:11:13 CST
descripton: C++ Lambda 表达式介绍



为了说明问题,先给一段简单的测试代码.

0. 测试代码:

#include <stdio.h>
constexpr auto square = [](int x) constexpr { return x * x; };
constexpr int val = square(4);  // 编译时计算得 16
int main()
{
	printf("%d\n",val);
	int v=square(3); //编译时计算得9
	printf("%d\n",v);
	int a=10;
	auto add_a = [a](int x){return x+a;};
	v=add_a(20);
	printf("%d\n",v);
	return 0;
}

运行代码:
$ ./tt
16
9
30

1. Lambda表达式是什么?

Lambda表达式(也称为lambda函数或匿名函数)是一种语法糖,
当我们书写代码时,发现需要定义一个函数, 但此时我们无需去另外找一个地方去书写这个函数.
而是就在你需要调用的地方开始书写函数体代码.
好处是方便, 随用随定义. 调用和实现是紧挨着的.
这个Lambda表达式的格式如下:
[capture] (parameters) -> return_type { body }

捕获列表(capture) :定义了Lambda表达式可以访问的外部变量。捕获方式有两种:按值捕获(value)和按引用捕获(reference)。
参数列表(parameters) :定义了Lambda表达式的输入参数。如果不需要参数,可以省略参数列表的括号。
返回类型(return_type) :定义了Lambda表达式的返回类型。如果不需要显式指定返回类型,可以使用auto或省略返回类型。
函数体(body) :包含Lambda表达式的执行代码。
如果与函数比较, 我们会发现它有参数列表,有返回值和函数体,但没有函数名.多了一个捕获列表.

2. lambda 表达式本质上是一个匿名类,

编译器会自动生成一个匿名类(未命名的类),
以第一个lambda 表达式为例.
其大致等价于:
class __AnonymousLambdaClass {
public:
int operator()(int x) const {
return x * x;
}
};
实例化这个类,得到一个对象,起名square, 属于函数对象

auto square = [](int x) { return x * x; }; 语句解释
[] (这里为空表示不捕获任何外部变量)
(int x) 是参数列表
{ return x * x; } 是函数体
square : 类对象

看看gdb中打印的,这个对象就是一个没有数据域的对象.
(gdb) p square
$1 = {}
看看gdb中打印的类型. 写的很简单.
(gdb) ptype square
type = const struct <lambda(int)> {
}

3. 为什么叫"函数对象" (Functor)?

因为该匿名类重载了 operator(),使得对象可以像函数一样调用:
int result = square(5); // 等价于 square.operator()(5);

其实square 函数对象等价于传统的square函数
int square(int x) { return x * x; }
函数对象的调用square(5) 也与传统的函数调用square(5)一致.

4 lambda 表达式有捕获变量的能力:

如果 lambda 捕获了变量(例如 [a]),生成的类会有对应的成员变量:
有人把捕获变量的能力叫闭包. 也有人叫携带状态

举例:
int a = 10;
auto add_a = [a](int x) { return x + a; };
// 捕获列表中有一个外部变量a,
// 生成类中会有一个成员变量存储 a 的副本, 这就是捕获的实现.
class __AdderLambdaClass {
private:
int _a; // 捕获的变量
public:
__AdderLambdaClass(int a) : _a(a) {}
int operator()(int x) const {
return x + _a;
}
};
看看gdb 中的输出, 对象以及类型一目了然!
(gdb) p add_a (对象)
$1 = {
__a = 10
}
(gdb) ptype add_a (类)
type = struct <lambda(int)> {
int __a;
}

所以说,lambda 表示式并不是什么神秘的东西, 它是一种替代传统的
定义函数,调用函数二步走,改变为定义lambda表达式和调用它一步走(代码都在一起)的简易处理手段.
其内部实现方式是定义了一个匿名类并重载了operator()函数,使得对象能像函数一样调用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值