- 捕捉列表:由0个或多个“捕捉项"组成,并以逗号分隔。
eg:
auto retval = [=,&a,&b]()mutable->int {
printf("inner c[%d]\n",c);
a = 10;
b = 20;
return a+b;
};
(1) [var]表示值传递方式捕捉变量var
(2)[=]表示值传递方式捕捉所有父作用域的变量(包括this)
(3) [&var]表示引用传递捕捉变量var
(4) [&]表示引用传递捕捉所有父作用域的变量(包括this)
(5) [this]表示值传递方式捕捉当前的this指针
需要注意的地方:
- lambda函数是一个closure(闭包)类型的函数;
- lambda函数在编译时进行转换;
- lambda捕获的值是否可以修改,需要确认是否有mutable修饰。
- 默认引用捕获可能带来的悬挂引用问题
#include <iostream>
auto get_fun1(int x)
{
return [=]() {
std::cout << "= x: " << x << std::endl;
};
}
auto get_fun2(int x)
{
return [&]() {
std::cout << "& x: " << x << std::endl;
};
}
int main()
{
auto f1 = get_fun1(10);
auto f2 = get_fun2(10);
f1();
f2();
return 0;
}
输出:
= x: 10
& x: 0
- 注意this的生命周期
#include <iostream>
#include <functional>
#include <vector>
#include <memory>
#include <algorithm>
using FP = std::function<void()>;
std::vector<FP> fun_list;
class A {
public:
A(int x, int y) : m_x(x), m_y(y) {}
void print()
{
fun_list.push_back(
[=]() {
std::cout << "x: " << m_x << ", y: " << m_y << std::endl;
}
);
}
private:
int m_x;
int m_y;
};
int main()
{
std::unique_ptr<A> pA = std::make_unique<A>(10, 20);
pA->print();
//此处注释的部分,如果调用了reset,对象会被销毁,再次调用lambda时,this已经不存在。
//pA.reset(nullptr);
std::for_each(fun_list.begin(),fun_list.end(),[](FP p){
if(p)
p();
});
return 0;
}
- 引用捕获陷阱:引用捕获[&]别使用局部变量
- this陷阱:lambda里避免有全局变量或静态变量或者比当前类生命周期更长的变量
- 尽量避免使用复杂的lambda