开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
C++11中lambda特性
- lambda不支持重载,但是函数对象可以
class Cap
{
public:
bool operator()(int a, int b) { return a < b; }
bool operator()(float a, float b) { return a < b; }
};
- lambda不支持捕获具有静态存储时间的变量,如全局变量,静态变量
- mutable特性的lambda不能保存于const类型变量,类型不匹配
const auto f = [vec]()mutable {
for (auto i : vec)
{
std::cout << i;
}
};
- lambda表达式不能捕获成员变量,用this捕获即可
- 当捕获对象的生命周期小于lambda,则出现未定义行为
struct Baz
{
std::function<void()> f()
{
return [=]() {
std::cout << s << "\n";
};
}
std::string s;
};
void test()
{
auto f1 = Baz{ "111" }.f();
auto f2 = Baz{ "222" }.f();
f1();
f2();
}
这种问题的解决方法为(大于等于C++14):
struct Baz
{
std::function<void()>f()
{
return [ss=s]//这里是重点,将变量s保存到闭包中
()
{
std::cout << ss << "\n";
};
}
std::string s;
};
- 针对只移型别的对象不可按值捕获,可以通过引用捕获
std::unique_ptr<int> uptr = std::unique_ptr<int>(new int(10));
auto f = [&uptr]() {};
- 不捕获任何变量的lambda可以转换为函数指针
- The closure type associated with a lambda-expression has a deleted default constructor and a deleted copy assignment operator.
- The value of the value-captured variable is at the time the lambda is defined - not when it is used! The value of a ref-captured variable is the value when the lambda is used - not when it is defined.
- The C++ closures do not extend the lifetimes of the captured references. Be sure that the capture variable still lives when lambda is invoked.
C++14中lambda新特性
- 支持参数具有默认值
auto f = [](int x=10) {
std::cout << x << "\n";
};
f();
f(100);
- 支持带初始化列表的捕获
int x = 10;
auto f = [xx = x]//按值
() {
std::cout << xx << "\n";
};
f();//10
x = 100;
f();//10
int x = 10;
auto f = [&xx = x]//按引用
() {
std::cout << xx << "\n";
};
f();//10
x = 100;
f();//100
- 支持通用模板
auto f = [](auto x,int y) {
std::cout << x <<","<<y << "\n";
};
f(100, 0);
f("hello", 1);
f(1.2f, 2);
f(1.6, 3);
C++17中lambda新特性
- 支持*this捕获,适用于lambda表达式的生命周期大于对象的生命周期
- this和*this的取舍
In most cases, when you work inside the scope of a class, then [this] (or [&]) is perfectly fine. There’s no extra copy which is essential when your objects are large. You might consider [*this] when you really want a copy, and when there’s a chance a lambda will outlive the object.
- 支持std::invoke()实现立即调用,代替lambda表达式末尾的()
int x = 100, y = 0;
std::invoke([x = x, y = y]() {
std::cout << x <<","<<" "<<y << "\n";
}) ;
A lambda expression can read the value of a variable without capturing it if the variable
- has const non-volatile integral or enumeration type and has been initialised with a constant expression, or
- is constexpr and has no mutable members.