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 起)