C++20新特性_Lambda 改进

文章目录

  • [第一章 C++20核心语法特性](#第一章 C++20核心语法特性)
    • [1.9 Lambda 改进](#1.9 Lambda 改进)
      • [1.9.1. 模板Lambda使用](#1.9.1. 模板Lambda使用)
      • [1.9.2 废弃[=]隐士捕获](#1.9.2 废弃[=]隐士捕获)
      • [1.9.3 支持constexpr Lambda表达式](#1.9.3 支持constexpr Lambda表达式)
      • [1.9.4 无状态 Lambda 的默认构造与赋值](#1.9.4 无状态 Lambda 的默认构造与赋值)
      • [1.9.5 包展开](#1.9.5 包展开)

本文记录C++20新特性之Lambda 改进。

第一章 C++20核心语法特性

1.9 Lambda 改进

Lambda 表达式自 C++11 引入以来,已成为现代 C++ 编程不可或缺的一部分。C++20 对 Lambda 进行了多项重要的增强,使其在泛型编程、编译期计算以及捕获机制上变得更加强大和安全。

下面对Lambda的改进进行总结说明。

1.9.1. 模板Lambda使用

这是Lambda最明显的改进,直接在Lambda后边加了。

作用:允许我们访问类型名 T,或者对类型进行约束。

语法:[](T x) { ... }

使用举例:

cpp 复制代码
  void test()
  {
      // C++14 写法,使用auto,但很难获取vector 内部的类型T
      auto old_lambda = [](auto vec)
      {
		using T  = typename decltype(vec)::value_type; 
              T temp = vec[0];
		std::cout << temp << std::endl;
       };
vector<int> vec = { 1,2,3 };
old_lambda(vec);
      // 1

// C++20 写法,使用模板参数
      auto new_lambda = []<typename T>(const std::vector<T>& vec)
      {
          T temp = vec[0];
          std::cout << temp << std::endl;
};
new_lambda(vec);    
      // 1 
  }

1.9.2 废弃[=]隐士捕获

在 C++20 之前,[=] 会隐式捕获 this 指针。如果你在一个对象的成员函数中创建了一个 Lambda 并异步执行,而该对象在 Lambda 执行前被销毁了,Lambda 内部访问成员变量时就会崩溃(因为 this 悬空了)。

在C++20中,[=] 不再 隐式捕获 this。如果需要捕获,必须显示写出, [=,this]

cpp 复制代码
    struct Worker 
    {
        int value = 100;

        void doWork() {
            // C++17: [=] 默默捕获了 this,容易让人误以为是拷贝了 value
            // C++20: 编译器会警告,建议显式写出 [=, this]
            auto lambda = [=, this]() {
                return value; // 访问 this->value
            };
        }
    };

1.9.3 支持constexpr Lambda表达式

C++17 中 Lambda 可以在 constexpr 中使用,但限制较多。C++20 进一步放宽了限制,使得 Lambda 可以用于更多的编译期计算场景,甚至作为非类型模板参数。

cpp 复制代码
    void test()
    {
        // C++20: Lambda 可以直接在编译期求值
        constexpr auto add = [](int a, int b) { return a + b; };

        static_assert(add(10, 20) == 30); // 编译期断言通过
    }

1.9.4 无状态 Lambda 的默认构造与赋值

在 C++20 之前,即使 Lambda 没有捕获任何变量(无状态),也不能被默认构造或赋值。这使得我们很难将 Lambda 类型用作 std::map 的 Key 或存储在某些容器中。

C++20 允许无状态 Lambda 进行默认构造和赋值。

cpp 复制代码
    int test() 
    {
        auto greater = [](int a, int b) 
            { 
                return a > b;
            };

        // C++20 之前:编译错误,decltype(greater) 没有默认构造函数
        // C++20:合法
        std::map<int, int, decltype(greater)> myMap;

        // 也可以直接赋值
        decltype(greater) g2;
        g2 = greater;

        return 0;
    }

1.9.5 包展开

在C++20中,可以在Lambda捕获列表中直接展开参数包。

cpp 复制代码
	// 接收0个或多个参数的包装函数
    template<typename ... Args>
    void wrapper(Args&& ... args)
    {
        // C++20: 直接转发参数包到 Lambda
        auto lambda = [](auto&& ... innerArgs) {
            // 使用 C++17 折叠表达式来处理参数包
            std::cout << "Lambda received: ";
            // 这个表达式会展开,依次打印所有参数,并用空格分隔
            ((std::cout << innerArgs << " "), ...);
            std::cout << std::endl;

        };
        lambda(std::forward<Args>(args)...);
	}

    void test()
    {
        // 调用1:传入不同类型的字面量
        wrapper(10, "hello", 3.14, 'A');
        // Lambda received: 10 hello 3.14 A
        
        // 调用2:传入变量
        std::string my_str = "world";
        int my_int = 42;
        wrapper(my_str, my_int);
        // Lambda received: world 42
    }
}
相关推荐
ice_junjun8 天前
C++20 线程返回值处理指南
c++20·c++ 多线程返回值
晨非辰8 天前
C++ 波澜壮阔 40 年:类的封装、实例化与 this 指针详解,面向对象的核心
运维·c++·人工智能·后端·python·深度学习·c++40周年
凌乱风雨121111 天前
从源码角度解析C++20新特性如何简化线程超时取消
前端·算法·c++20
shuai132_20 天前
【无标题】
c++20
ULTRA??22 天前
基于range的函数式编程C++,python比较
c++·python·kotlin·c++20
apocelipes22 天前
从源码角度解析C++20新特性如何简化线程超时取消
c++·性能优化·golang·并发·c++20·linux编程
ALex_zry23 天前
C++20和C++23 在内存管理、并发控制和类型安全相关优化方式的详细技术分析
安全·c++20·c++23
ALex_zry23 天前
C++20/23标准对进程间共享信息的优化:从传统IPC到现代C++的演进
开发语言·c++·c++20
fpcc1 个月前
c++20容器中的透明哈希
哈希算法·c++20
小老鼠不吃猫1 个月前
C++20 STL <numbers> 数学常量库
开发语言·c++·c++20