Lecture 13 λ表达式
问题的提出
对于下面求定积分的函数:
double integrate(double (*f)(double), double a, double b);
如果要求函数x^2
在区间[0,1]的定积分,则一般要先定义一个函数square:
double square(double x) { return x*x; }
然后再把它作为参数去调用integrate:
integrate(square,0,1);
如果还要再求函数x^3
、…等一些在程序中很少使用的简单函数的定积分呢?
匿名函数–λ表达式
对于一些临时用一下的简单函数,如果也要先给出这个函数的定义并为之取个名字,然后再通过这个函数的名字来使用它们,在有些场合下会给程序编写带来不便。
C++新国际标准(C++11)为C++提供了一种匿名函数机制――λ表达式(lambda expression),利用它可以实现把函数的定义和使用合而为一。
例如,求函数x2在区间[0,1]的定积分:
integrate([](double x)->double { return x*x; },0,1);
//上面第一个参数就是一个λ表达式
λ表达式的定义格式
λ表达式的常用格式为:[<环境变量使用说明>]<形式参数><返回值类型指定><函数体>
-
<形式参数>
:指出函数的参数及类型,其格式为:(<形式参数表>)
- 如果函数没有参数,则这项可以省略。
-
<返回值类型指定>
:指出函数的返回值类型,其格式为:-> <返回值类型>
- 它可以省略,这时根据函数体中return返回的值隐式确定返回值类型。
-
<函数体>
为一个复合语句。 -
<环境变量使用说明>
:指出函数体中对外层作用域中的自动变量的使用限制:- 空:不能使用外层作用域中的自动变量。
&
:按引用方式使用外层作用域中的自动变量(可以改变这些变量的值)。=
:按值方式使用使用外层作用域中的自动变量(不能改变这些变量的值)。- &和=可以用来统一指定对外层作用域中自动变量的使用方式,也可以用来单独指定可使用的外层自动变量(变量名前可以加&,默认为=)。
下面是一些合法的λ表达式:
{ int k,m,n; //环境变量
......
...[](int x)->int { return x*x; }... //不能使用k、m、n
...[&](int x)->int { k++; m++; n++;
return x+k+m+n; }... //k、m、n可以被修改
...[=](int x)->int { return x+k+m+n; }... //k、m、n不能被修改
...[&,n](int x)->int { k++; m++;
return x+k+m+n; }... //n不能被修改
...[=,&n](int x)->int { n++; return x+k+m+n; }... //n可以被修改
...[&k,m](int x)->int { k++; return x+k+m; }... //只能使用k和m,k可以被修改
...[=] { return k+m+n; }... //没有参数,返回值类型为int
}
-
λ表达式通常用于把一个匿名函数作为参数传给另一个函数的场合。
-
不使用环境变量的λ表达式可隐式转换成函数指针。
λ表达式的实现
在C++中,λ表达式是通过函数对象来实现的:
-
对于λ表达式:
[...](int x)->int { ....... }
-
首先,隐式定义一个类:
- 数据成员对应用到的环境变量,用构造函数对其初始化。
- 重载了函数调用操作符,重载函数按相应λ表达式的功能来实现。
-
然后,创建上述类的一个临时对象(设为obj)
-
最后,在使用上述λ表达式的地方用该对象来替代:
-
作用于实参进行函数调用
cout << obj(3);
-
传给其它函数
f(obj);
-