Lambda表达式

Lambda表达式

  • Lambda 表达式是现代 C++ 中最重要的特性之一,而 Lambda 表达式,实际上就是提供了一个类似匿名函数的特性, 而匿名函数则是在需要一个函数,但是又不想费力去命名一个函数的情况下去使用的。这样的场景其实有很多很多, 所以匿名函数几乎是现代编程语言的标配。

语法

  • lambda表达式基本语法如下:
    [捕获列表](参数列表) mutable(可选) 异常属性 -> 返回类型 {
    // 函数体
    }
    
  • 捕获列表:其实可以理解为参数的一种类型,Lambda 表达式内部函数体在默认情况下是不能够使用函数体外部的变量的, 这时候捕获列表可以起到传递外部数据的作用。根据传递的行为,捕获列表也分为以下几种:

1.值捕获:

  • 与参数传值类似,值捕获的前提是变量可以拷贝,不同之处则在于,被捕获的变量在 Lambda 表达式被创建时拷贝, 而非调用时才拷贝
void Lambda_value_capture()
{
    int value = 1;
    auto copy_value = [value]
    {
        return value;
    };

    value = 100;
    std::cout<<copy_value()<<std::endl;  // 1
}

2.引用捕获:

  • 与引用传参类似,引用捕获保存的是引用,值会发生变化
void Lambda_reference_capture()
{
    int value = 1;
    auto copy_value = [&value]
    {
        return value;
    };

    value = 100;
    std::cout<<copy_value()<<std::endl; // 100
}

3.隐式捕获:

  • 手动书写捕获列表有时候是非常复杂的,这种机械性的工作可以交给编译器来处理,这时候可以在捕获列表中写一个 & 或 = 向编译器声明采用引用捕获或者值捕获
    void Lambda_implicit_capture()
    {
        int value = 1;
        auto copy_value_1 = [&]
        {
            return value;
        };
    
        auto copy_value_2 = [=]
        {
            return value;
        };
    
        value = 100;
        std::cout<<copy_value_1()<<std::endl;  // 100
        std::cout<<copy_value_2()<<std::endl;  // 1
    }
    
  • 总结一下,捕获提供了 Lambda 表达式对外部值进行使用的功能,捕获列表的最常用的四种形式可以是:
    • [] 空捕获列表
    • [name1, name2, ...] 捕获一系列变量
    • [&] 引用捕获, 让编译器自行推导引用列表
    • [=] 值捕获, 让编译器自行推导值捕获列表

4.表达式捕获:

  • 上面提到的值捕获、引用捕获都是已经在外层作用域声明的变量,因此这些捕获方式捕获的均为左值,而不能捕获右值
  • C++14 给与了我们方便,允许捕获的成员用任意的表达式进行初始化,这就允许了右值的捕获, 被声明的捕获变量类型会根据表达式进行判断,判断方式与使用 auto 本质上是相同的:
#include <iostream>
#include <memory>  // std::make_unique
#include <utility> // std::move

void lambda_expression_capture() {
    auto important = std::make_unique<int>(1);
    auto add = [v1 = 1, v2 = std::move(important)](int x, int y) -> int {
        return x+y+v1+(*v2);
    };
    std::cout << add(3,4) << std::endl;
}

5.泛型Lambda

  • 从 C++14 开始,Lambda 函数的形式参数可以使用 auto 关键字来产生意义上的泛型:
    auto add = [](auto x, auto y) {
        return x+y;
    };
    
    add(1, 2);
    add(1.1, 2.2);
    

参考

posted @ 2023-05-23 16:44  scyrc  阅读(43)  评论(0编辑  收藏  举报