• C++11之lambda表达式解析


    什么是Lanmbda?

      简短函数,就地书写。常用于向函数(算法)传递函数参数。

     

    语法

      Lambda 表达式,[capture](paras)mutable->return type{statement} 全部语法格式,分如下章节介绍:

    • [capture]: 捕获列表。捕获列表,总是出现在 lambda 函数的开始处。事实上[ ]是lambda 的引用符。换句话说,编译器根据引出符判断接下来的代码是否是 lamba 函数。
    • (paramers): 参数列表。与普能函数的参数列表一致。如果不需要传递参数,可以连同()一起省略。
    • mutable: 默认情况下,lambda 函数总是一个 const 函数,mutable 可以取消其常量性。在使用该修饰符时,参数列表不可以省略(即使参数为空)。
    • ->return-type: 返回类型。用于追踪返回类型形式声明函数的返回类型。出于方便,不需要返回值的时候可以连同->一起省略。此外返回类型明确的情况下,也可以省略该部分。编译器可以自行推导。
    •  {statement}: 函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。

     

    格式1——[]{}闭包+函数体

    #include <iostream>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
        auto foo = []{ return 1 +2 ;};
        cout<<foo();
        cout<<[]{ return 1 +2 ;}()<<endl;
        return 0;
    }

     

    格式2——[](){}闭包+参数+函数体

    格式3——[]()->{}闭包+参数+返回值+函数体

    #include <iostream>
    using namespace std;
    int main(int argc, char *argv[])
    {
        auto foo = [](int x, int y)->int{return x + y;};
        cout<<foo(1,2)<<endl;
        cout<<[](int x, int y){return x + y;}(1,2)<<endl;
        return 0;
    }

    格式4——[]()mutable->{}闭包+参数+可修改+返回值+函数体

    #include <iostream>
    using namespace std;
    int main(int argc, char *argv[])
    {
        int x = 10; int y = 100;
        cout<<"main:"<<x<<y<<endl;
        auto foo = [=]()mutable{
                                x = 20;
                                y = 200;
                                cout<<"lambda:"<<x<<y<<endl;
                                };
        foo();
        cout<<"main:"<<x<<y<<endl;
        return 0;
    }            

    ———————————————模块说明—————————————————

    []闭包

     lambda 函数能够捕获 lambda 函数外的具有自动存储时期的变量。函数体与这些变
    量的集合合起来叫闭包。闭包的概念在 lambda 中通过[]来体现出来。

    • [] 不截取任何变量。[bar] 仅对外部变量 bar 值传递在函数体中使用。
    • [&bar] 仅对外部变量 bar 引用传递在函数体中使用。
    • [x, &y] x 值传递y 引用传递在函数体中使用。。
    • [&} 截取外部作用域中所有变量,并作为引用传递在函数体中使用。
    • [=] 截取外部作用域中所有变量,并按值传递在函数体中使用。
    • [=, &foo] 截取外部作用域中所有变量,并值传递在函数体中使用,但是对 foo变量使用引用传递。
    • [&, =foo] 截取外部作用域中所有变量,在函数体中作引用传递使用,但是对foo 变量作值传递。 

      上述,中涉及到值传递要发生拷贝行为,而引用传递则不会发生拷贝行为。捕获列表中不允许重复。比如:[=, a] [&,&this]。闭包的本质,初始化 lamda 表达式。 

    mutable 作用——截取值 还是截取引用?

    int main()
    {
        int i=42;
        auto f=[i](){return i+=5;};
        i=0;
        auto j=f();
        cout<<"i="<<i<<endl;
        cout<<"j="<<j<<endl;
    
        return 0;
    }

      运行此函数会提示:error: assignment of read-only variable 'i'    auto f=[i](){return i+=5;};
      

      说明{return i+=5;}内的i是受到保护的,无法修改。如果此时将[i](){return i+=5;};改为 [&i](){return i+=5;};就能通过编译,由于传入的是引用,所以i的改变是
      执行结果:
      i=5;
      j=5;

    mutable加持!

    int main()
    {
        int i=42;
        auto f=[i](){return i+=5;};
        i=0;
        auto j=f();
        cout<<"i="<<i<<endl;
        cout<<"j="<<j<<endl;
      
        auto f1=[i](){return i+=5;};
       cout<<"k="<<k<<endl;
        return 0;
    }

      如果将表达式改为[i]()mutable{return i+=5;};也可以通过,mutable改变了{return i+=5;} i 的const属性,也可以通过编译。

      运行结果:
      i=0;
      j=47;

      K=5;

    这说明了什么?
      lambda表达式中[i]值的捕获是发生在编译期的!执行时此时 i=42 值早已拷贝传入。所以 i 之后的改变对于表达式运行并无任何影响。

      也就是说,当声明时lambda表达式对外部变量(i)以赋值的方式捕获后赋给一个“函数指针”,执行该函数指针时,捕获的变量 (i) 不与外部发生任何关系,无论外部变量如何改变。要想重新“刷新”内部变量,需要重新声明该lambda表达式。
      

      mutable参数只对只[]闭包中捕获的(非引用)值才有作用。对于()传入的参数没有任何影响。

     

     

     

  • 相关阅读:
    MYSQL数据丢失讨论【转】
    MySQL 5.6 新功能之 Index Condition Pushdown (ICP)
    MySQL Binlog 【ROW】和【STATEMENT】选择
    MySQL open_files_limit相关设置
    Python颜色输出和random的学习
    Python 之 【二进制、十进制、八进制、十六进制 】之间的转换【转】
    初识 MySQL 5.5 新功能、参数
    Oracle Inventory关键词解释
    plsql 输出当月的所有日期
    ORA29279: SMTP permanent error: 550 XXX@XX.com... No such user
  • 原文地址:https://www.cnblogs.com/wangkeqin/p/9285895.html
Copyright © 2020-2023  润新知