c++ 之Lambda表达式
Lambda表达式
Lambda 表达式是 C++11 引入的一种匿名函数的方式,它允许你在需要函数的地方内联地定义函数,而无需单独命名函数
基本语法如下
[capture clause](parameters) -> return_type {
// 函数体
// 可以使用捕获列表中的变量
return expression; // 可选的返回语句
}
[捕获列表](参数列表) -> 参数类型 {};
Lambda 表达式由以下部分组成:
- 捕获列表(Capture clause)
主要用于捕获外部的变量,在 Lambda 表达式中可以访问这些变量。捕获列表可以为空,也可以包含变量列表 [var1, var2, …]。 - 参数列表(Parameters)
这就跟普通函数的参数列表很像,可以为空。 - 返回值类型(return_type)
Lambda表达式可以做到自动推断返回类型,也可以显式的给它自定返回类型。如果函数体只有一条返回语句,可以省略返回类型。 - 函数体(Body)
Lambda 表达式的函数体,包含需要执行的代码。
Lambda表达式简单应用(实现加法的功能)
#include <iostream0>
using namespace std;
int main()
{
int x = 30;
int y = 20;
auto add = [](int a, int b) -> int{
return a + b;
};
int ret = add(x, y);
cout << ret << endl;
return 0;
}
以上就是一个捕获列表为空,的一个Lambda表达式的简单应用。
Lambda函数充当匿名函数
我们先回忆一下回调函数的写法,下面要实现找最大值的功能
#include <iostream>
using namespace std;
bool compare(int a, int b)
{
return a > b;
}
int getMax(int a, int b, bool (*compare)(int a, int b))
{
if(compare(a, b))
{
return a;
}
else
{
return b;
}
}
int main()
{
int x = 30;
int y = 20;
// 回调函数的形式
int max = getMax(x, y, compare);
cout << max << endl;
return 0;
}
下面改装成匿名的Lambda函数来实现
#include <iostream>
using namespace std;
bool compare(int a, int b)
{
return a > b;
}
int getMax(int a, int b, bool (*compare)(int a, int b))
{
if(compare(a, b))
{
return a;
}
else
{
return b;
}
}
int main()
{
int x = 30;
int y = 20;
// 回调函数的形式
// int max = getMax(x, y, compare);
int max = getMax(x, y, [](int a, int b) -> bool{
return a > b;
});
cout << max << endl;
return 0;
}
带参数捕获的Lambda表达式使用
大致有以下三种方式
- 指定参数的捕获
#include <iostream>
using namespace std;
int main()
{
int x = 4;
int y = 5;
int z = 6;
auto add = [x, y]() -> int{
// x = 10; 这种方式捕获,是不能修改变量值的,是只读的。
return x + y;
};
int ret = add();
cout << ret << endl;
return 0;
}
add 中的 x
和 y
是在 Lambda 定义时的值的拷贝。
- 使用 = 进行所有参数的捕获
auto mul = [=]() -> int{
// = 这种方式捕获所有变量,无需在列表中写明
// x = 10; 照样是无法修改的,只读的。
return x * y * z;
};
ret = mul();
cout << ret << endl;
和第一种方式同理, x
和 y
是在 Lambda 定义时的值的拷贝。
- 使用 & 进行所有参数的捕获
// 用引用的方式来捕获,引用类似指针,进行地址访问
auto modifyAndMul = [&]() -> int{
x = 15; // 引用的方式进行所有变量的捕获,可读可写。
return x * y * z;
};
ret = modifyAndMul();
cout << ret << endl;
cout << "x = " << x << endl;
表示它按引用捕获所有外部变量。因此,它可以修改 x 和 y 的原始值。
Lambda函数 vs 内联函数
特性 | Lambda 函数 | Lambda 函数 |
---|---|---|
定义 | 一种匿名函数,通常用于定义在需要它们的地方。 | 一种常规函数,通过 inline 关键字定义。 |
用途 | 提供一种快捷方式来定义临时的、小型的函数。 | 用于优化小型函数,减少函数调用的开销。 |
语法 | 使用 [capture] (params) { body } 的形式定义。 | 使用常规函数定义语法,但在前面加上 inline 关键字。 |
生命周期 | 在定义它们的作用域内有效。 | 在整个程序执行期间有效。 |
捕获外部变量 | 可以捕获外部作用域中的变量(按值或按引用)。 | 不能直接捕获外部变量,只能通过参数传递。 |
调用方式 | 作为函数对象,可直接调用。 | 像普通函数一样调用。 |
优化 | 可以被编译器自动内联化,但这取决于编译器优化策略。 | 明确请求编译器尝试内联,但实际内联化也取决于编译器。 |
可见性 | 通常只在定义它们的局部作用域内可见。 | 可以在定义它的任何作用域内可见。 |
使用场景 | 适合于一次性使用的场景,如作为回调、在算法中使用等。 | 适合于频繁调用的小型函数。 |
请注意,虽然 Lambda 函数和内联函数在某些方面有相似之处,如它们都可以被编译器优化以减少调用开销,但它们在设计和用途上有明显的不同。
Lambda 函数的核心优势在于它们的匿名性和对外部变量的捕获能力,而内联函数则主要关注于提高小型函数的性能。