C++ 中的 Lambda 表达式是一种匿名函数,可以方便地创建并传递函数对象。这是 C++11 引入的一项重要功能,可以大大提高代码的可读性和简洁性。
以下是一个深入讲解 C++ 使用 Lambda 表达式的例子,包括基本语法、捕获列表、函数调用、以及与 STL 的结合使用等。
Lambda基本语法
首先,我们来看一个最简单的 lambda 表达式:
[](){/* do nothing */};
这个 lambda 表达式定义了一个空函数,没有参数,也没有返回值。你可以将其看作是一个没有实体的具名函数。
你还可以定义带有参数的 lambda 表达式:
[](int a, float b){return a + b;};
这个函数接收两个参数,一个是 int 类型的 a,另一个是 float 类型的 b。它的返回值是 a 和 b 的和。
你也可以定义带有默认参数的 lambda 表达式:
[](int a, float b = 0.0f){return a + b;};
这个函数和上一个函数功能基本相同,只是 b 参数的默认值是 0.0f。
Lambda的捕获列表
你还可以在 lambda 表达式中捕获外部变量的值:
int a = 10;
float b = 20.0f;
auto add = [&a, &b]() { return a + b; }; // 使用引用捕获外部变量
std::cout << add() << std::endl; // 输出 30
在这个例子中,&a 和 &b 是通过引用来捕获 a 和 b 的值的。这意味着 lambda 表达式可以修改捕获的变量的值。如果你只想在 lambda 表达式中使用外部变量的值,而不修改它们的值,你应该使用值捕获而不是引用捕获。例如:
int a = 10;
float b = 20.0f;
auto add = [a, b]() { return a + b; }; // 使用值捕获外部变量
std::cout << add() << std::endl; // 输出 30
在这个例子中,虽然 a 和 b 的值被传递给了 lambda 表达式,但是 lambda 表达式并不能修改它们的值。
Lambda与函数调用
你可以将 lambda 表达式作为一个函数参数传递给其他函数。例如,你可以使用一个 lambda 表达式来作为 std::sort 函数的比较函数:
std::vector<int> v = {5, 3, 1, 4, 2};
std::sort(v.begin(), v.end(), [](int a, int b) {return a < b;}); // 使用 lambda 表达式作为比较函数
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; // 输出 1 2 3 4 5
在这个例子中,lambda 表达式 [](int a, int b) {return a < b;} 被传递给了 std::sort 函数,用于比较 v 中的元素。这意味着你可以用 lambda 表达式来实现自定义的算法和数据结构。
Lambda与 STL 的结合使用
下面我们再来看一个比较复杂但很有用的例子:使用 lambda 表达式和 STL 来查找一个 vector 中第一个出现的不重复的元素:
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_set>
int main() {
std::vector<int> v = {1, 2, 3, 2, 4, 3, 5, 6, 4};
auto it = std::find_if(v.begin(), v.end(), [&](int a) {
return std::find(std::begin(un), std::end(un), a) == std::end(un);
});
}
在这个例子中,我们使用了一个较为复杂的 lambda 表达式来作为 std::find_if 函数的比较函数。这个 lambda 表达式接收一个参数 a,然后使用一个名为 un 的 std::unordered_set 来查找 a 是否第一次出现。这个例子展示了如何使用 lambda 表达式和 STL 来解决一个复杂的问题。