C++ Weekly - Episode 133 脱水版: What Exactly IS A Lambda
Lambda到底是什么
Lambda 实际上可以和一个可调用对象等价。参见以下几种情况:
- 无参无捕获 lambda
// 等价于 auto lam_1 = __lambda_0();
auto lam_0 = [](){ return 5; };
struct __lambda_0
{
auto operator()() const {
return 5;
}
};
- 有参无捕获 lambda
// 等价于 auto lam_1 = __lambda_1();
auto lam_1 = [](int i){ return i + 5; };
struct __lambda_1
{
auto operator()(int i) const {
return i + 5;
}
};
- 有参有捕获 lambda
// 等价于 auto lam_3 =__lambda_3{ .__val = val};
auto lam_3 = [val](int i){ return i + val + 5; };
struct __lambda_3
{
int __val;
auto operator()(int i) const {
return i + __val + 5;
}
};
这里需要注意的是, 由于 lambda 函数默认带有 const 属性, 因此我们无法在 lambda 内部修改捕获的变量 (假如修改 val 值),否则编译器将会报错:
error: cannot assign to a variable captured by copy in a non-mutable lambda
- mutable lambda
如果需要修改捕获变量,我们需要通过关键字 mutable 来修饰 lambda 表达式, 此时相当于移除了表达式或者可调用对象的 const 属性,如下:
// 等价于 auto lam_4 =__lambda_4{ .__val = val};
auto lam_4 = [val](int i) mutable { return i + (val++) + 5; };
struct __lambda_4
{
int __val;
auto operator()(int i) {
return i + (__val++) + 5;
}
};
- 模板 lambda
// 等价于 auto lam_5 =__lambda_5{ .__val = val};
auto lam_5 = [val](auto i) { return i + val + 5; };
struct __lambda_5
{
int __val;
template<typename T>
/* constexpr */ auto operator()(T i) const {
return i + __val + 5;
}
};
需要注意的一点是,C++17 开始,可调用对象会尽可能地返回 constexpr 的表达式。但是如果是捕获了局部变量,将会阻止编译器返回 constexpr.