C++11-lambda表达式

时间:2021-08-20 19:10:26

1.语法形式

lambda表达式定义了一个匿名函数,其本质就是一个匿名的彷函数对象:

[ 捕获表 ](参数表) 选项 -> 返回类型 { 函数体 }


嵌入式函数

[] (int x) ->{return x*x;};//实现了小括号运算符的类对象

cout<< [] (int x) ->{return x*x;}(100)<<endl;//10000

//只能写auto
auto fun=cout<< [] (int x) ->{return x*x;};
||
||
||
class <编译器生成类名>
{
public:
int operator()(int x)const
{
return x*x;
}
private:
成员变量来自捕获表;
};

lambda表达式的值就是《编译器生成的类名》类型的对象

cout<<fun(100)<<endl;//10000

cout<<fun(200)<<endl;//40000


=========================================================

普通函数

int fun(int x){return x*x;}

cout<<fun(100)<<endl;//10000

#include <iostream>
#include <vector>
#include <typeinfo>
#include <algorithm>
using namespace std;
void print (int x) {
    cout << x << ' ';
}
bool intCmp (int x, int y) {
    return x > y;
}
int main (void) {
    auto f1 = [] (int x = 10) -> int { return x * x; };
    /*
    class Z4mainEUliE_ {
    public:
        int operator() (int x = 10) const {
            return x * x;
        }
    };
    Z4mainEUliE_ f1;
    */
    cout << typeid (f1).name () << endl;
    cout << f1 () << ' ' << f1 (13) << ' ' << f1 (14) << endl;
    cout << [] (int x = 10) -> int { return x * x; } (15)<<endl;
//    cout << Z4mainEUliE_ () (15) << endl;
    // 编译器可以根据return语句自动推导返
    // 回类型,因此返回类型可以省略不写
    auto f2 = [] (int x = 10) { return x * x; };
    cout << f2 (16) << endl;
    // 列表初始化不能用于返回类型的自动推导 
//    auto f3 = [] (void) { return vector<int> {10, 20, 30}; };
//    auto f3 = [] (void) -> vector<int> { return {10, 20, 30}; };
    // 空参数表可以省略void
//    auto f3 = [] () -> vector<int> { return {10, 20, 30}; };
    // 空参数表且返回类型可自动推导可以省略"()"
    auto f3 = [] { return vector<int> {10, 20, 30}; };
    for (auto a : f3 ())
        cout << a << ' ';
    cout << endl;
    vector<int> vi {40, 10, 50, 20, 30};
    sort (vi.begin (), vi.end (), intCmp);
    sort (vi.begin (), vi.end (),
        [] (int x, int y) { return x > y; });
    for_each (vi.begin (), vi.end (), print);
    cout << endl;
    for_each (vi.begin (), vi.end (),
        [] (int x) { cout << x << ' '; });
    cout << endl;
    return 0;
}

 

2.捕获列表

【】 不捕获任何外部变量

【d】 按值捕获外部变量d

【&d】 按引用捕获外部变量d

【this】 捕获this指针

【=】 按值捕获所有的外部变量,包括this指针

【&】 按引用捕获所有的外部变量,包括this指针

【=,&d】 按值捕获除d以外的外部变量(包括this指针),按引用捕获外部变量d

【&,d】 按引用捕获除d以外的外部变量(包括this指针),按值捕获外部变量d


**注意:按值捕获不可以修改变量的值,按引用捕获可以修改变量的值

mutable :在lambda中可以修改按值捕获的外部变量,这样的lambda表达式,其参数表必须显示写出,不可省略

3.不捕获任何外部变量的lambda表达式可以被隐式转换为函数原型相同的函数指针

#include <cmath>
#include <iostream>
using namespace std;
int a = 10;
class Base {
protected:
    int b = 20;
};
class Derived : public Base {
public:
    void foo (int d = 40) {
        [] (int e) {
            cout << __FUNCTION__ << endl;
            cout << a << endl;
//            cout << b << endl;
//            cout << c << endl;
//            cout << d << endl;
            cout << e << endl;
        } (50);
        [d] (int e) {
            cout << __FUNCTION__ << endl;
            cout << a << endl;
//            cout << b << endl;
//            cout << c << endl;
            cout << d << endl;
            cout << e << endl;
        } (50);
        [d,this] (int e) {
            cout << __FUNCTION__ << endl;
            cout << a << endl;
            cout << b << endl;
            cout << c << endl;
            cout << d << endl;
            cout << e << endl;
        } (50);
        [=] (int e) {
            cout << __FUNCTION__ << endl;
            cout << ++a << endl;
            cout << ++b << endl;
            cout << ++c << endl;
            cout << /*++*/d << endl;
            cout << ++e << endl;
        } (50);
        [&] (int e) {
            cout << __FUNCTION__ << endl;
            cout << ++a << endl;
            cout << ++b << endl;
            cout << ++c << endl;
            cout << ++d << endl;
            cout << ++e << endl;
        } (50);
        [=,&d] (int e) {
            cout << __FUNCTION__ << endl;
            cout << ++a << endl;
            cout << ++b << endl;
            cout << ++c << endl;
            cout << ++d << endl;
            cout << ++e << endl;
        } (50);
    }
private:
    int c = 30;
};
int main (void) {
    cout << "输入两条直角边的长度:" << flush;
    int a, b;
    cin >> a >> b;
    cout << "斜边的长度:" << [] (int a, int b) {
        return sqrt (a * a + b * b); } (a, b) << endl;
    cout << "斜边的长度:" << [a, b] {
        return sqrt (a * a + b * b); } () << endl;
    /*
    class ??? {
    public:
        ??? (int& a, int& b) : a (a), b (b) {}
        int operator() (void) const {
            return sqrt (a * a + b * b);
        }
    private:
//        int const a, b;
        int& a, b;
    };
    cout << "斜边的长度:" << ??? (a, b) () << endl;
    */
    Derived obj;
    obj.foo ();
    int x = 60;
    auto f1 = [x] { cout << x << endl; };
    ++x;
    f1 (); // 60
    int y = 70;
    auto f2 = [&y] { cout << y << endl; };
    ++y;
    f2 (); // 71
    int z = 80;
    auto f3 = [=] { cout << /*++*/z << endl; };
    auto f4 = [=] () mutable { cout << ++z << endl; };
    f4 (); // 81
    cout << z << endl; // 80
    auto f5 = [&] { cout << ++z << endl; };
    f5 (); // 81
    cout << z << endl; // 81
    auto f6 = [/*=*/] (int x, int y) -> int {
//        cout << z << endl;
        return sqrt (x * x + y * y); };
    cout << f6 (3, 4) << endl;
    int (*pfun) (int, int) = f6;
    cout << pfun (3, 4) << endl;
    return 0;
}