跳转至

lambda

lambda 由 4 部分组成,如下: - [] 捕获列表 - () 参数列表 - -> 返回值类型 - {} 函数体

示例代码

int x=0,y=0;
auto f = [x,&y](const std::string&str)->int{...};

1 基础知识

1.1 语法形式

[capture list] (parameter list) -> return type
{
   function body;
};

1.2 捕获列表 [ ]

  • 作用:引入外部变量供 lambda 函数中使用
  • [this] : 捕获 this 指针,捕获 this 指针可以让我们使用 this 类型的成员变量和函数 (可访问 private)。
  • [=] : 捕获 lambda 表达式定义作用域的全部变量的值,包括 this。只读数据,不能修改
  • [&] : 捕获 lambda 表达式定义作用域的全部变量的引用,包括 this。可以修改数据
  • [x,&y] : 指定 lambda 函数内能使用的变量 x by value,y by reference, 注意不能使用 [&y,=] 格式
  • [=,&y] : 指定 y by reference 传进来,其它以 by value 传进来
  • [=, *this]{}; : C++17 前,错误:无效语法;C++17 起,OK:捕获 this 对象的副本
  • [=, this] {}; : C++20 前,错误:= 为默认时的 this;C++20 起,OK:同 [=]
  • 示例 [=, *this]{};
class Work  
{  
private:  
int value;  
public:  
Work() : value(42) {}  
std::future<int> spawn()  
{  
return std::async([=, *this]() -> int { return value; });  
}  
};
title: 那些变量能够被捕获?

1. 能捕获的变量必须是一个自动存储类型。简单来说就是非静态的局部变量。
title: 哪些变量不能被捕获,能直接使用?

1. 该变量是全局变量。
2. 具有静态或线程局部存储期变量。
3. 该变量是以常量表达式初始化的引用。
  • 示例
#include <iostream>  
int x = 1;  
int main()  
{  
int y = 2;  
static int z = 3;  
auto foo = [y] { return x + y + z; };  
std::cout << foo() << std::endl;  
}
在捕获this时,如果是异步场景,this可以提前析构,这时会出现未定义行为。这种场景使用c++14支持的叫作初始化捕获
class Work  
{  
private:  
int value;  
public:  
Work() : value(42) {}  
std::future<int> spawn()  
{  
return std::async([=, tmp = *this]() -> int { return  
tmp.value; });  
}  
};

1.3 参数列表 ( )

  • 有参时,如 [ ](char c){...};
  • 无参情况可以不写,也可以写 (),如 [ ](){...};[ ]{...};

1.4 返回类型 ->

  • 有返回值时,如 [ ]()->int{...};
  • 无返回值时 ,可不写,如 [ ](){...};[ ]()->void{...};

1.5 示例

#include <iostream>
#include <string>
int main()
{
    int x = 1;
    int y = 1;
    auto f = [x,&y](const std::string&str)->int{
    std::cout << "执行lambda" << std::endl;
    std::cout << str << std::endl;
   // x++;  //by value不可修改
    y++;    //by reference 可修改
    return 1;
    };
    std::cout << "还未调用lambda" << std::endl << std::endl; 
    std::cout << f("你好")<<std::endl;
    std::cin.get();
}

2 泛型 lambda - auto(C++14)

lambda 表达式具备了模版函数的能力,我们称它为泛型 lambda 表达式。不需要使用 template 关键字,函数参数使用 auto 占位符即可。

  • 示例
int main()  
{  
  auto foo = [](auto a) { return a; };  
  int three = foo(3);  
  char const* hello = foo("hello");  
}

3 泛型 lambda - template(C++20)

C++14 标准中 lambda 表达式通过支持 auto 来实现泛型。C++20 中可以用真正的 template 来实现泛型。

  • [ 捕获 ] < 模板形参 > 约束 (可选) ( 形参列表 )(可选) lambda 说明符 { 函数体 } (2) (C++20 起) (C++23 前)
  • [ 捕获 ] < 模板形参 > 约束 (可选) 属性 (可选) ( 形参列表 )(可选) lambda 说明符 { 函数体 }(2) (C++23 起)