前言
Lambda 表达式是 C++11 引入的一种便捷的匿名函数特性,它允许你在需要函数对象的地方写下一个快速的内联函数。Lambda 表达式对于STL算法或任何需要函数作为参数的场合特别有用,它可以简化代码,增加灵活性和可读性。
一、基本语法
Lambda 表达式的基本语法如下:
[捕获列表](参数列表) -> 返回类型 {
函数体
}
捕获列表:定义了 lambda 函数体外的哪些变量可以被该 lambda 使用,以及是以值传递还是以引用传递的方式使用它们。
参数列表:就像普通函数一样,用于定义传入 lambda 的参数。
返回类型:可选项。大多数情况下,编译器可以自动推导 lambda 的返回类型。
函数体:包含了 lambda 表达式要执行的代码块。
二、捕获列表
1.捕获列表的几种形式
- [] 不捕获任何外部变量。
- [x, &y] 按值捕获 x,按引用捕获 y。
- [=] 捕获所有外部变量(在 lambda 表达式创建时)的副本。
- [&] 以引用方式捕获所有外部变量。
- [=, &x] 按引用捕获 x,其余变量都按值捕获。
- [&, x] 按值捕获 x,其余变量都按引用捕获。
2. 捕获指针
将一个指针作为捕获变量传递到 lambda 表达式中,可能会影响其释放,具体取决于捕获变量的类型和如何管理其生命周期。
假设捕获变量为ss, 让我们分析一下可能的情况:
- 如果 ss 是一个共享指针(std::shared_ptr):在这种情况下,将 ss 作为捕获变量传递到 lambda 表达式中将增加其引用计数。这意味着只要 lambda 表达式存在,ss 将不会被释放,即使原始的共享指针已经被销毁或重置。这可能会导致资源泄露,如果 lambda 长时间存在或者没有被正确释放。
- 如果 ss 是一个弱指针(std::weak_ptr):在这种情况下,捕获 ss 到 lambda
表达式中不会增加其引用计数,因此不会阻止 ss 的释放。这是处理可能长时间存在的回调时的一种更安全的方法,因为它允许资源被适当地释放,即使 lambda 仍然存在。 - 如果 ss 是一个裸指针或其他类型的指针:捕获这样的指针到 lambda 表达式中不会自动管理其生命周期。在这种情况下,你需要确保 ss 在 lambda 存在期间仍然有效,同时还要确保在不再需要时正确地释放资源。
考虑到这些情况,最好的做法通常是使用 std::weak_ptr 来捕获这种可能长时间存在的回调中的资源,以避免潜在的资源泄露。
3. 示例代码
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> v = {4, 1, 3, 5, 2};
// 使用 lambda 表达式作为比较函数
std::sort(v.begin(), v.end(), [](int a, int b) {
return a < b; // 升序排序
});
// 打印排序后的 vector
for(int i : v) {
std::cout << i << " ";
}
return 0;
}
总结
Lambda 表达式是 C++11 引入的一种功能,允许定义匿名函数对象直接在需要它们的地方。Lambda 表达式广泛应用于 STL 算法、事件处理、并行计算等场合,提高了代码的简洁性和灵活性。