C++11 Lambda表达式(匿名函数)详解

说明
Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。
格式
[capture list] (parameter list) ->return type {function body}
例子

#include <stdio.h>
#include <string>
#include <functional>
#include <memory>

static int  g_var = 1;

class Widget
{
public:
    Widget()
    {
        printf("widget\n");
    }
    Widget(const Widget& )
    {
        printf("copy widget\n");
    }
    ~Widget()
    {
        printf("~widget\n");
    }
    void test() const
    {
        printf("widget test\n");
    }

    void test1() const
    {
        printf("widget test1\n");
    }

};

int main()
{
    //[capture list] (parameter list) ->return type {function body}

    //1.完整的例子
    {
        auto fun = [](int a,int b)->int{return  a+b;};
        //输出30
        printf("%d\n",fun(10,20));
    }

    //2.可以忽略参数列表 和 返回值. 如果有返回值,则自动推导类型,否则为void
    {
        auto fun=[]{return  40;};
        //输出40
        printf("%d\n",fun());
    }

    //3.使用捕获列表例子
    {
        int var  = 50;
        auto fun = [var]{return  var+1;};
        //输出51
        printf("%d\n",fun());
    }

    //3.1值捕获,即lambda创建时拷贝 但是不能在在lambda函数体内修改值
    {
        int var  = 40;
        int var1  = 60;

        //值拷贝 捕获
        auto fun = [var,var1]
        {
            //var = 1;  错误 不能改值
            return  var+var1;
        };

        var = 10;
        var1 = 20;

        //输出100
        printf("%d\n",fun());
    }

    //3.2 引用捕获,即lambda创建时采用引用方式捕获,引用捕获应保证变量在lambda没执行完前不能消失
    {
        int var  = 40;
        int var1  = 60;

        //var采用引用方式捕获 var1采用拷贝捕获
        auto fun = [&var,var1]{return  var+var1;};

        var = 10;
        var1 = 20;

        //输出70
        printf("%d\n",fun());
    }
    //3.3  隐式值捕获  编译器根据lambda中的代码自动推导
    {
        int  var = 80;
        auto fun = [=]{return  var;};
        //输出80
        printf("%d\n",fun());
    }

    //3.3  隐式引用捕获  编译器根据lambda中的代码自动推导
    {
        int  var = 80;
        auto fun = [&]{return  var;};
        var = 90;
        //输出90
        printf("%d\n",fun());
    }
    //3.4 混合引用 显式捕获和隐士捕获必须使用不同的方式,即不能同时为值捕获或者引用捕获
    {
        std::string str("10");
        int var = 90;
        auto fun = [=,&str]{return  (atoi(str.c_str()) + var);};
        //输出100
        printf("%d\n",fun());
    }

    //3.5使用值捕获,加上mutable就可以在lambda函数体内修改值
    {
        int var  = 50;
        auto fun = [var]()mutable{ var=110; return  var;};
        //输出 50  110
        printf("%d %d\n",var,fun());
    }

    //3.6使用引用捕获,是否可以修改依赖于是否有const修饰
    {
        int var  = 50;
        const int var1 = 60;
        auto fun = [&]{
            var=120;
            // var1 = 130;  const 不能修改
            return  var;
        };
        //输出 120  120 60
        printf("%d %d %d\n",var,fun(),var1);
    }

    //3.6 static值不能被捕获
    // lambda 不仅依赖局部变量和形参(它们能被捕获)
    // 还依赖静态存储期  即定义在全局或名字空间作用域中 类 函数等 以 static修饰  这样的对象可以在lambda 中使用  但不能捕获
    {
        static int var  = 50;
        int var1  = 70;

        //var 不能被捕获,var1值被拷贝捕获了
        auto fun = [=]{
            return  var+var1+g_var;
        };

        //错误  var不能被捕获
        //        auto fun1 = [var,var1]{
        //            return  var+var1;
        //        };

        //错误  var不能被捕获
        //        auto fun2 = [&var,var1]{
        //            return  var+var1;
        //        };


        //输出 50 121
        printf("%d %d\n",var,fun());

        var = 60;
        g_var = 2;
        //输出 60 132
        printf("%d %d\n",var,fun());
    }

    printf("-----------------------------\n");
    //对象值捕获
    {
        Widget w;
        //调用拷贝构造函数
        auto fun= [=]{w.test();}; // test 必须是const
        fun();
    }
    printf("-----------------------------\n");
    //对象引用捕获
    {
        Widget w;
        auto fun= [&]{w.test1();};
        fun();
    }

    printf("-----------------------------\n");
    //移动捕获
    {
        Widget w ;

        auto fun = std::bind(
                    []( Widget& w){w.test1();},
                std::move(w)
                );

        fun();
    }

    //转换为函数指针
    {
        int (*fun)(int, int)=[](int a,int b){return a+b;};//不捕获时才可转换为函数指针
        printf("%d\n",fun(1,2));
    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值