C++11:lambda表达式

这个实现的效果类似于匿名函数,不像C++98/03那样一个函数所有人都能调用,不公开不必要的接口,提高程序安全性。
首先来写个最简单的lambda表达式。

1
[]{};

对,5个字符就成为了一个lambda表达式了,虽然并没卵用,不过至少跨出了一步。这个lambda表达式实际上是精简后的表达式。不加以精简的话,原表达式应该像这样:

1
[](){};

看起来挺简单的,我也这么觉得:)
解释下,首先一对方括号代表捕获列表,含义后面再解释。然后是一对圆括号,代表lambda函数的参数列表,当参数为空可省略这对圆括号,就像上面5个字符的lambda表达式这样。接下来是一对大括号,这个和函数的大括号没什么区别了,里面可以加代码,可以加return。

下面我们来实现一个lambda表达式,用来计算两个int数字的和

1
2
3
auto sum = [] (int a, int b) {
    return a+b;
};

这儿为了方便,使用auto自动生成类型。调用方式也简单,直接 sum(3,5); 就行了,返回的类型为自动推导类型。
关于这个类型,目前我知道的,有两种形式保存,一种是通过函数指针。这种方式只能对捕获列表,也就是那对中括号为空的lambda函数进行保存,代码如下:

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;
using pSum = int (*)(int, int);//C++11新特性,类型重定义,效果与  typedef int (*pSum)(int, int);  完全相同
 
int main (int argc, char* argv []) {
    pSum sum = [] (int a, int b) {
        return a + b;
    };
    cout << sum (3, 5) << endl;
    return 0;
}

结果呐,对你没猜错,就是8。
接下来就是针对捕获列表不为空的情况了,下面说下捕获列表的作用。捕获列表是在函数中定义lambda表达式时,用于方便获取局部变量的值或引用。

1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;
 
int main (int argc, char* argv []) {
    int i = 5;
    [&i] () { i = 3; }();
    cout << i << endl;
    return 0;
}

定义lambda后直接调用,直接在lambda函数后面加一对圆括号传参就行了。这儿我定义了一个变量i,然后通过捕获列表传入i的引用,然后对i进行重新赋值。程序运行结果为3。关于捕获的引用传递与值传递的区别是,值传递后变量不可更改,引用传递后变量可修改。上面我传的是引用,使用“&i”,值传递直接写个 i 就行了。
这儿可以写多个引用或值传递。如果一次性需要引入所有局部变量,那么写个 [&] 代表引用所有,写个 [=]代表传递所有的值。传值后的变量不可修改,有办法能加个可修改属性,如下代码:

1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;
 
int main (int argc, char* argv []) {
    int i = 5;
    [i] () mutable { i = 3; }();
    cout << i << endl;
    return 0;
}

mutable表示可以修改值传递的数据,但不影响函数的局部变量。上面这代码的程序运行结果还是5。
那么这样的lambda表达式如何存储呢?这得通过std::function。如下代码演示如何存放包含捕获的lambda表达式

1
2
3
4
5
6
7
8
9
#include <iostream>
#include <functional>
using namespace std;
 
int main (int argc, char* argv []) {
    function<int (int, int)> f = [] (int a, int b) { return a + b; };
    cout << f (3, 5) << endl;
    return 0;
}

计算两个数字之和的lambda表达式,除了通过函数指针外,也可通过function存储。这儿没有写捕获列表,写了也能存储。

Published by

fawdlstty

又一只萌萌哒程序猿~~

发表评论

电子邮件地址不会被公开。 必填项已用*标注