这里写自定义目录标题
写在前面
当谈到 C++11 新特性,Lambda 表达式是其中最重要且最受欢迎的功能之一。Lambda 表达式允许我们在需要函数对象的地方,以一种简洁、灵活且内联的方式定义一个短小的、即时的匿名函数。Lambda表达式通常用于简化代码、使代码更具可读性,并在需要时提供一个可定制的行为。
基本语法
[capture list](parameters) -> return_type
{
// 函数体
}
capture list: 用于捕获外部变量,可以为空。通过捕获外部变量,Lambda函数可以访问在其定义位置范围内的变量。
parameters: 用于指定Lambda函数的参数列表,与普通函数的参数列表相似。
return_type: 用于指定Lambda函数的返回类型。可以使用C++11的类型推断机制来自动推断返回类型,也可以明确指定返回类型。
{}:包含Lambda函数的函数体,实现函数的具体逻辑。
Lambda表达式的使用
举一些例子
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
int x = 10;
auto add = [x](int a, int b) { return a + b + x; };
cout << add(3, 5) << endl; // 输出:18
return 0;
}
上述代码中使用lambda表达式定义了一个名为add的函数对象,这个add的作用就是将传进来的两个函数参数a,b相加再加上外部变量x的和,并返回。这里没有给出返回值类型,程序员易于发现(只有一个return的情况),C++11的类型推断机制可以自动推断返回类型。
你可能会想这和普通的函数没什么区别,函数嵌套也一直存在着我们的代码中,接下来介绍它经常被使用到的地方
在算法函数中
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> numbers = {5, 2, 10, 8, 3};
// 使用Lambda表达式排序numbers,按照从小到大的顺序
sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a < b;
});
// 使用Lambda表达式遍历numbers,输出每个元素的平方
cout << "Squared numbers: ";
for_each(numbers.begin(), numbers.end(), [](int num) {
cout << num * num << " ";
});
cout << std::endl;
// 使用Lambda表达式计算numbers中所有元素的和
int sum = 0;
for_each(numbers.begin(), numbers.end(), [&sum](int num) {
sum += num;
});
cout << "Sum of numbers: " << sum << std::endl;
return 0;
}
在上面的例子中,我们使用了三个Lambda表达式:
1、在sort函数中,使用Lambda表达式来指定排序规则,按照从小到大的顺序排序numbers容器。
2、在std::for_each函数中,使用Lambda表达式来遍历numbers容器,并输出每个元素的平方。
3、在第二次使用std::for_each函数中,使用Lambda表达式来计算numbers容器中所有元素的和,并通过捕获列表将变量sum引入Lambda函数内部,易于知道,变量前加&是进行引用传递,不加&是值传递,即传的外部变量的副本,不改变其本身的值。
Lambda表达式的优势在于它能够减少代码中的冗余,并且能够在需要临时函数时快速创建一个短小的函数逻辑。
STL或自定义容器的比较函数
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 定义一个结构体
struct Person {
string name;
int age;
// 构造函数
Person(const string& n, int a) : name(n), age(a) {}
};
int main() {
// 使用lambda表达式来定义自定义的比较函数
// 以Person结构体的age成员变量为排序依据,按照递减顺序排序
std::sort(people.begin(), people.end(), [](const Person& a, const Person& b) {
return a.age > b.age;
});
return 0;
}
在这个例子中,我们定义了一个名为Person的结构体,其中包含了姓名name和年龄age这两个成员变量。我们使用std::sort算法对people向量进行排序,并传递了一个lambda表达式作为比较函数。在lambda表达式中,我们通过a.age和b.age来访问结构体Person的年龄成员,然后按照年龄的递减顺序进行排序。
接下来再来看一个使用lambda表达式自定义构造堆(priority_queue)
#include <iostream>
#include <queue>
using namespace std;
int main() {
// 使用lambda表达式实现自定义的比较(最小堆,升序排列)
auto compare = [](int a, int b) {
return a > b; // 使用递减顺序,数值大的优先级高,和sort是反着的
};
priority_queue<int, std::vector<int>, decltype(compare)> minHeap(compare);
minHeap.push(5);
minHeap.push(2);
minHeap.push(8);
while (!minHeap.empty()) {
cout << minHeap.top() << " ";
minHeap.pop();
}//输出为 2 5 8
return 0;
}
注意:在构造priority_queue时,我们将lambda表达式compare的类型作为第三个模板参数,并在创建minHeap对象时传递了这个lambda表达式到构造函数。这样,minHeap就使用了我们自定义的比较函数,从而实现了相应的优先级规则。
注意事项
一、捕获列表
捕获列表(Capture List):Lambda函数可以捕获外部变量,即在函数体中访问Lambda函数定义处范围内的变量。捕获列表使用方括号[ ]来指定,可以为空表示不捕获任何变量。捕获列表有两种方式:
值捕获(Value Capture):捕获外部变量的副本。
[=]:表示捕获lambda表达式定义作用域所有的变量的副本。
引用捕获(Reference Capture):通过引用捕获外部变量,可以在Lambda函数中修改捕获的变量。
[&]:表示捕获lambda表达式定义作用域所有的变量的引用。
int x = 5;
auto lambda1 = [x]() { cout << x << endl; }; // 值捕获,x的值在Lambda函数中不可修改
auto lambda2 = [&x]() { cout << x << endl; }; // 引用捕获,x的值在Lambda函数中可修改
二、参数列表
参数列表(Parameters):与普通函数一样,Lambda函数可以接受参数。参数列表使用小括号()指定。可以为空,表示不接受任何参数。
auto add = [](int a, int b) { return a + b; };
cout << add(3, 2) << endl; // 输出:5
三、返回类型
返回类型(Return Type):Lambda函数可以自动推断返回类型,也可以显式指定返回类型。当函数体较复杂或有多个返回路径时,显式指定返回类型是推荐的做法。
auto square = [](int x) -> int { return x * x; };
cout << square(4) << endl; // 输出:16
四、Lambda作为函数对象
Lambda作为函数对象:Lambda函数本质上是一个函数对象,可以像普通函数对象一样传递给其他函数或作为返回值。
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
// 函数接受一个Lambda函数并将其应用于容器中的每个元素
void process(vector<int>& data, const function<void(int)>& func) {
for (int num : data) {
func(num);
}
}
int main() {
vector<int> numbers = {1, 2, 3, 4, 5};
// 使用Lambda函数作为参数调用process函数
process(numbers, [](int x) { std::cout << x << " "; });
// 输出:1 2 3 4 5
return 0;
}
写在后面
Lambda表达式是C++11引入的重要特性,它为编写更简洁、灵活和高效的代码提供了方便的工具。在现代C++开发中,Lambda表达式广泛应用于标准库算法、并发编程、回调函数等场景。它的出现大大简化了代码编写,提升了C++语言的表达力和编程效率。