C++20 新式lambda
外观
C++20新式Lambda是C++20标准中对Lambda表达式的重大改进,引入了模板参数、可构造可赋值性增强、捕获包展开等特性,使Lambda更接近普通函数的表达能力。本文将详细介绍这些改进及其应用场景。
核心改进概览[编辑 | 编辑源代码]
C++20的Lambda表达式主要包含以下改进:
- 支持模板参数列表
- 允许显式对象参数(`this`捕获的替代方案)
- 默认构造和赋值操作(无状态Lambda)
- 支持捕获参数包展开
- 简化`constexpr` Lambda的隐式声明
模板参数列表[编辑 | 编辑源代码]
C++20允许Lambda使用模板语法,解决了C++14泛型Lambda无法指定类型约束的问题。
// C++20 模板Lambda示例
auto lambda = []<typename T>(T x, T y) {
return x + y;
};
int main() {
std::cout << lambda(3, 4); // 输出: 7
std::cout << lambda(3.5, 4.2); // 输出: 7.7
}
对比C++14的泛型Lambda:
// C++14 泛型Lambda(无法指定类型约束)
auto lambda = [](auto x, auto y) { /*...*/ };
显式对象参数[编辑 | 编辑源代码]
新增`[*this]`捕获和显式对象参数语法,解决悬垂引用问题:
struct S {
int x;
auto get_lambda() {
// C++17捕获*this副本
return [*this] { return x; };
// C++20等效写法
return [](this const S& self) { return self.x; };
}
};
无状态Lambda的构造[编辑 | 编辑源代码]
无捕获的Lambda现在默认可构造和可赋值:
auto lambda1 = []{};
decltype(lambda1) lambda2; // C++20允许默认构造
lambda2 = lambda1; // C++20允许赋值
捕获参数包展开[编辑 | 编辑源代码]
支持在捕获子句中展开参数包:
template<typename... Args>
void process(Args... args) {
// 捕获所有参数副本
auto lambda = [...args = std::move(args)] {
(std::cout << ... << args); // 折叠表达式
};
lambda();
}
int main() {
process(1, " ", 2.0, "\n"); // 输出: 1 2
}
实际应用案例[编辑 | 编辑源代码]
STL算法定制[编辑 | 编辑源代码]
std::vector<std::string> v{"apple", "banana"};
std::sort(v.begin(), v.end(),
[]<typename T>(const T& a, const T& b) {
return a.length() < b.length();
});
元编程场景[编辑 | 编辑源代码]
constexpr auto factorial = []<int N>(std::integral_constant<int, N>) {
return N * factorial(std::integral_constant<int, N-1>{});
};
template<>
constexpr auto factorial<0>(std::integral_constant<int, 0>) {
return 1;
};
特性对比表[编辑 | 编辑源代码]
特性 | C++11 | C++14 | C++17 | C++20 |
---|---|---|---|---|
模板参数 | ❌ | 泛型Lambda | ❌ | 完整支持 |
捕获*this | ❌ | ❌ | ✅ | ✅(语法改进) |
默认构造 | ❌ | ❌ | ❌ | ✅ |
包展开捕获 | ❌ | ❌ | ❌ | ✅ |
注意事项[编辑 | 编辑源代码]
- 模板Lambda需要编译器完全支持C++20标准
- 显式对象参数语法与成员函数冲突时优先解析为成员函数
- 捕获包展开可能增加编译时间
通过以上改进,C++20的Lambda表达式已成为更强大的工具,既保持了简洁语法,又获得了接近普通函数的表达能力。建议在实践中逐步尝试这些新特性,特别注意模板Lambda带来的类型安全优势。