跳转到内容

C++20 新式lambda

来自代码酷


C++20新式Lambda是C++20标准中对Lambda表达式的重大改进,引入了模板参数、可构造可赋值性增强、捕获包展开等特性,使Lambda更接近普通函数的表达能力。本文将详细介绍这些改进及其应用场景。

核心改进概览[编辑 | 编辑源代码]

C++20的Lambda表达式主要包含以下改进:

  • 支持模板参数列表
  • 允许显式对象参数(`this`捕获的替代方案)
  • 默认构造和赋值操作(无状态Lambda)
  • 支持捕获参数包展开
  • 简化`constexpr` Lambda的隐式声明

graph TD A[C++11 Lambda基础] --> B[C++14泛型Lambda] B --> C[C++17 constexpr Lambda] C --> D[C++20模板Lambda] D --> E[捕获包展开] E --> F[显式对象参数]

模板参数列表[编辑 | 编辑源代码]

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标准
  • 显式对象参数语法与成员函数冲突时优先解析为成员函数
  • 捕获包展开可能增加编译时间

Lambda复杂度=O(模板参数数量×捕获变量数编译器优化级别)

通过以上改进,C++20的Lambda表达式已成为更强大的工具,既保持了简洁语法,又获得了接近普通函数的表达能力。建议在实践中逐步尝试这些新特性,特别注意模板Lambda带来的类型安全优势。