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
    }
}
相关推荐
Mr_WangAndy10 小时前
C++17 新特性_第二章 C++17 语言特性_std::any和string_view
c++·string_view·c++40周年·c++17新特性·c++新特性any
Mr_WangAndy13 小时前
C++17 新特性_第一章 C++17 语言特性___has_include,u8字符字面量
c++·c++40周年·c++17新特性·__has_include·u8字面量
Mr_WangAndy21 小时前
C++17 新特性_第二章 C++17标准库特性_std::invoke和std::invoke_result_t
c++·invoke·c++40周年·c++17新特性·invoke_result
Mr_WangAndy1 天前
C++14 新特性_第二章 C++14 标准库特性_std::exchange,std::quoted
c++·exchange·c++40周年·quoted·c++14新特性
Mr_WangAndy1 天前
C++17 新特性_第一章 C++17 语言特性_if constexpr,类模板参数推导 (CTAD)
c++·c++40周年·if constexpr·类模板参数推导 ctad·c++17新特性
止观止2 天前
告别“祖传C++”:开启你的现代C++之旅
c++·c++11·c++20·编程思想·现代c++
Mr_WangAndy2 天前
C++14新特性_第一章C++语言特性_Lambda初始化捕获,decltype(auto)
c++·c++40周年·lambda初始化捕获·decltype auto
Chrikk2 天前
【下篇】C++20 约束、NCCL 通信与并发模型
c++·c++20·c++40周年
不知所云,2 天前
6. c++ 20 Modules 使用
开发语言·c++20·c++ modules