返回随笔C++
旧稿归档ENGINEERING NOTE

STL:lambda 表达式

记录 lambda 的参数、捕获列表、返回类型和可变状态,并说明它与泛型算法的配合方式。

C++STLlambda

lambda表达式概览

可以向算法传递任何类型的可调用对象,这其中包括函数,函数指针,还有重载了调用运算符()的类,以及lambda表达式。lambda表达式的行为类似于函数,可以对其使用调用运算符和传递参数。lambda表达式的一般结构为:

[捕获列表] (参数列表) -> 返回类型{函数体}

可以忽略返回类型和参数列表。当忽略返回类型时,返回类型根据return的类型自动推断,否则类型为void。不加()表明忽略参数列表,等价于指定一个空参数列表(空括号)。

auto f = [] { return 42; };

向lambda传递参数

参数列表括号中可以添加对lambda传递的参数。

//一个具有比较功能的lambda表达式
auto f = [](const int& a, const int& b) { return a < b; };
//使用lambda表达式的sort
sort(vec.begin(), vec.end(), f);

使用捕获列表

空捕获列表表示不会使用表达式所在函数中的任何参数。可以在参数列表中给定所需参量,该参量必须在表达式之前声明。

int ve = 5;
auto f = [ve](const int& a) { return a < ve; };

可以传递多个参量,之间使用逗号隔开:

int ve, i;
auto f = [ve, i](const int& a) { return a + i < ve; };

lambda的捕获和返回

值捕获和引用捕获

[ve] { return ve; };   //值捕获
[&ve] { return ve; };  //引用捕获

使用引用捕获必须保证在语句执行时引用仍然存在。如果捕获了迭代器,迭代器很有可能在语句执行时失效。

隐式捕获

可以向[]中传递=或者&来表示捕获的类型,这样当语句中出现函数中的变量时,它将遵循赋值或引用。可以不显示告知捕获类型。

[&](const int& a) { b++; };
[=](const int& a) { return a < b; };

可以使用混合类型,指定特定的捕获为特定类型。

[=, &b]() { return b < c; };
[&, b]() { return b < c; };

如果默认类型为引用,显示指定的类型必须为赋值,即不能有[&, &b]() { return b < a; }存在,赋值也一样。

可变lambda

拷贝的捕获不能修改值(并不是像函数的临时变量一样不会影响原始变量,编辑器直接禁止此类操作)。若要在函数中修改其值(函数外该值仍然未变,这一点不同于引用捕获),需使用关键字mutable。

mutable有用情不专一的意思,真是笑死。

[b]() mutable{ return ++b; };
//执行后,lambda表达式中的b++,然而上一级函数中的b未变。

指定lambda的返回类型

lambda可以通过return自动推断返回类型,但当函数体中不仅仅存在return语句时,lambda自动返回void,此时需要显式指定返回类型。lambda使用->来指出返回的数据类型。

[](int a, int b) -> bool { if (a + b < 1) return true; 
                         else return false; };