Skip to content

C++11 features #16

@MoRunChang2015

Description

@MoRunChang2015

Lambda function

Lambda 函数/表达式也称匿名函数是C++11新加入的一个特性,可以以匿名的方式声明一个函数,这样的匿名函数大多数情况下会作为回调函数使用,也可以通过函数指针的方法给匿名函数一个名字用于调用,如以下例子:

#include <iostream>
#include <vector>

using namespace std;
int main() {
    auto p = []{ cout << "HaHa" << endl;};
    p();
    return 0;
}

编译运行会在命令行中输出“HaHa”字符串。
Lambda函数的基本格式是
[ 函数对象参数 ](函数参数)mutable/exception声明->返回类型{函数体}
接下来逐项来解释

  1. 函数对象参数
    这标识一个lambda的开始,所以这部分必须存在不能省略。函数对象参数是用于传递给编译器自动生成的函数对象类的构造函数。函数对象只能使用那些到定义lambda为止是lambda所在作用域可见的局部变量(保护this指针),函数对象参数有以下形式

    1.空,表示没有使用任何函数对象参数,函数体内不能使用外部的局部变量
    2.=,函数体内可以使用外部的局部变量,并且是按值传递的形式(默认以const形式传入)
    3.&, 函数体内可以使用外部的局部变量,并且是引用传递的形式
    4.this,函数体内可以使用llambda所在类中成员变量
    5.=/&, &a, b, 函数体内可以使用外部的局部变量,并且a是引用传递方式,b是值传递方式其他变量按照值/引用传递的方式。

2.函数参数,即传入函数的的参数,若没用参数时可以省略
3.mutable和exception声明,这部分也可以省略,加上mutable时,可以对按值传入的拷贝修改(修改拷贝的值)如下程序

#include <iostream>
#include <vector>

using namespace std;
int main() {
    int a = 1;
    auto p = [=]{ a = 2;cout << "HaHa" << endl;};
    p();
    return 0;
}

编译会出错因为a在lambda函数体里是const int类型不能修改它的只,只有加上mutable后

#include <iostream>
#include <vector>

using namespace std;
int main() {
    int a = 1;
    auto p = [=]()mutable{ a = 2;cout << "HaHa" << endl;};
    p();
    cout << a << endl;
    return 0;
}

编译可以通过,但是最后输出的a的值还是1,exception声明用于表示函数可以抛出的异常类,如需要抛出整形异常,只要加上throw(int),如下

#include <iostream>
#include <vector>

using namespace std;
int main() {
    int a = 1;
    auto p = [=]()throw(int){ throw(a);cout << "HaHa" << endl;};
    try{
        p();
    } catch(int e) {
        cout << a << endl;
    }
    return 0;
}

4.->返回值声明,用于标识返回值的类型,若为空则可以省略或者若编译器可以推断出返回类型也可省略。
5.函数体,函数执行语句,不可省略
lambda函数经常用于for_each的回调函数如下程序

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
int main() {
    vector<int> v;
    for (int i = 1;  i <= 5; i++)
        v.push_back(i);
    int total = 0;
    for_each(v.begin(), v.end(), [&](int v) {total += v;});
    cout << total << endl;
    return 0;
}

通过lambda作为回调函数计算1~5的和,结果输出为15

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions