【C/C++】C++11 Lambda

Lambda

C++11 中 lambda 是一个匿名函数对象

最简形式

[]{
    cout << "lambda" << endl;
}();    // print "lambda"

auto l = []{
    cout << "lambda" << endl;
};
...
l();    // print "lambda"

完整形式

[...](...) mutable throwSpec ->retType {...}

[...]:lambda 引入符,捕获 non-static 外部变量

  [] 不捕获外部变量

  [=] 传值

  [&] 传引用

  [x, &y] x 传值,y 传引用

  [=, &x] x 传引用,其余变量传值(尽量不这样写默认情况,而是全部列出,增加代码可读性)

(...):形参列表,若含以下可选参数之一,即使无形参,也必须加上 ()

可选参数

mutable:关键字,表明传入的外部变量在函数内可改动。若传值捕获外部变量,再加上 mutable 关键字,表明函数内变量可改动,但不会影响函数外该变量的值。

throwSpec:异常处理

->retType:lambda 的返回类型

{...}:函数体,函数体内可声明 static / non-static 变量,可返回数值

例子

 1 int main() {
 2     int id = 0;
 3     auto f = [id]() mutable {
 4         cout << "f() id: " << id << endl;
 5         ++id;
 6     };
 7     id = 99;
 8     f();    // print "f() id: 0" 
 9     f();    // print "f() id: 1"
10     f();    // print "f() id: 2"
11     cout << "id: " << id << endl;    // print "id: 99"
12     return 0;
13 }

注意:

1、编译器看到第 3 行的时候,id = 0,由于传值,所以函数内 id = 0

2、若不写 mutable,则 ++id 编译报错 “cannot assign a variable captured by copy in a non-mutable lambda”

3、若 id 定义为 static,则 static int id = 0 编译报错 “id cannot be captured because it does not have automatic storage duration(静态存储周期)”

比较(传引用)

 1 int main() {
 2     int id = 0;
 3     auto f = [&id]() mutable {
 4         cout << "f() id: " << id << endl;
 5         ++id;
 6     };
 7     id = 99;
 8     f();    // print "f() id: 99" 
 9     f();    // print "f() id: 100"
10     f();    // print "f() id: 101"
11     cout << "id: " << id << endl;    // print "id: 102"
12     return 0;
13 }

比较(有形参)

 1 int main() {
 2     int id = 0;
 3     auto f = [id](int p) {
 4         cout << "f() id: " << id << " p: " << p << endl;
 5         ++p;
 6     };
 7     id = 99;
 8     f(id);    // print "f() id: 0 p: 99"
 9     f(7);     // print "f() id: 0 p: 7"    
10     cout << "id: " << id << endl;    // print "id: 99"
11     return 0;
12 }

声明一个 lambda 对象,需要使用 template 或 auto。

如果需要 lambda 对象的类型,需要使用 decltype(),例如,将 lambda 作为哈希函数或排序准则,传给一个关联容器或无序容器时。

auto cmp = [](const Person& p1, const Person& p2) {
    return p1.lastname < p2.lastname || 
    (p1.lastname == p2.lastname && p1.lastname < p2.lastname);
}
...
std::set<Person, decltype(cmp)> coll(cmp);    // set的声明需要cmp的类型

这里必须使用 cmp 作为 set 构造函数的参数,否则编译器会尝试调用 cmp 对象的默认构造函数并报错。

注意,虽然 lambda 是一个函数对象,但无法为其设计默认构造函数和赋值操作。

原文地址:https://www.cnblogs.com/wayne793377164/p/9104050.html