1.前言

C++11 提供了对匿名函数的支持,称为 Lambda 函数(也叫 Lambda 表达式)。Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。

2.详解

2.1 语法介绍

Lambda 表达式本质上与函数声明非常类似。Lambda 表达式具体形式如下:

[capture](parameters)修饰符->return-type{func body}
// 例如:
[](int x, int y) -> int { int z = x + y; return z + x; } (2-1)

     如果没有返回值可以表示为:

[capture](parameters){body}
// 例如:
[](int x, int y){ return x < y ; } (2-2)

     *parameters:这一部分可以被省略(如果函数无参数),我们可以使用下面方式定义Lambda表达式

auto f = [] {
cout << "Hello" << '\n';
};

      还可以使用下面的方式:

auto f = [] (string s) {
cout << "Hello " << s << '\n';
};

     *修饰符:这一部分是可以省略的,常见的修饰符有两个,一个是mutable,另一个是exception

       mutable:当函数参数以值引用传递方式传递时,在函数体内是不可以修改该函数参数的值的,我们可以使用mutable修饰符,使得该函数参数可以在函数体内改变,下面我们实验一下:

int x = 1;
auto test = [x] () { x++; };
test();

   这样会报错,参数x是值传递的方式,是一个只读变量,但是我们加入mutable后,就不会报错

int x = 1;
auto test = [x] () mutable { x++; cout << x << ' '; }; // x只能在内部改变
test();cout << x << '\n'; // x值为1!!!!!!

 

     exception:exception 声明用于指定函数抛出的异常,如抛出整数类型的异常,可以使用 throw(int)。

2.2 注意事项

    以(2-1)Lambda表达式为例,一个临时的参数 z 被创建用来存储中间结果。如同一般的函数,z 的值不会保留到下一次该不具名函数再次被调用时。如果 lambda 函数没有传回值(例如 void),其返回类型可被完全忽略。

      在Lambda表达式内可以访问当前作用域的变量,这是Lambda表达式的闭包(Closure)行为。 与JavaScript闭包不同,C++变量传递有传值和传引用的区别。可以通过前面的[]来指定:

[]      // 沒有定义任何变量。使用未定义变量会引发错误。
[x, &y] // x以传值方式传入(默认),y以引用方式传入。
[&] // 任何被使用到的外部变量都隐式地以引用方式加以引用。
[=] // 任何被使用到的外部变量都隐式地以传值方式加以引用。
[&, x] // x显式地以传值方式加以引用。其余变量以引用方式加以引用。
[=, &z] // z显式地以引用方式加以引用。其余变量以传值方式加以引用。

    此外,还需要注意的是,对于[=]或[&]的形式,lambda 表达式可以直接使用 this 指针。但是,对于[]的形式,如果要使用 this 指针,必须显式传入:

[this]() { this->someFunc(); }();