zoukankan      html  css  js  c++  java
  • lambda expression & mutable

    一、Lambda表达式定义

      

    二、Lambda捕获方式

      

    三、Lambda使用

     1 void main()
     2 {
     3     int a = 1, b = 2;
     4     auto fn1 = []() {std::cout << "fn1
    "; };
     5     // auto fn1 = []() {std::cout << "fn1()" << a << "
    "; }; // Error1
     6     auto fn2 = [](int m, int n) {std::cout << "fn2(a, b) = " << m + n << "
    "; };
     7     auto fn3 = [](int m, int n)->int {return m + n; };
     8     // auto fn3 = [](int a, int b) {return a + b; } // Error2
     9     auto fn4 = [&]()->int {a = 10; b = 20; return a + b; }; 
    10     // auto fn4 = [=]()->int {a = 10; b = 20; return a + b; }; // Error3
    11     auto fn5 = [=]()->int {return a + b; };
    12     auto fn6 = [a, &b]()->int {b = 20; return a + b; };
    13     // auto fn6 = [a, &b]()->int {a = 10; b = 20; return a + b; }; // Error4
    14 
    15     fn1();
    16     fn2(a, b);
    17     fn3(a, b);
    18     fn4();
    19     fn5();
    20     fn6();
    21 }
    • [] 可以为空,默认不捕获任何变量
    • [&]对Lambda表达式可见的变量进行引用捕获
    • [=]对Lambda表达式可见的变量进行之捕获
    • [a, &b]对指定的变量进行值或引用捕获

      是否注意到被注释的代码部分,这些都是错误的写法。Error1:Lambda表达式未捕获任何变量,所以其内部不可使用外部的变量;Error2(3, 4):Lambda表达式内部不可对值捕获的变量进行修改,如果需要修改需要使用另外的方式。通过上面错误例子

    引出今天的主题:为什么Lambda表达式值捕获的变量不可在其内部修改?如果需要修改,改如何实现?

    四、Lambda & mutable

      看如下定义的函数:

    1 void Func(int a)
    2 {
    3     a = 10;
    4     std::cout << "a = " << a << std::endl;
    5 }

      调用者通过值传递的方式调用Func,在函数内部可以修改形参变量a,但是不影响实参a;这个原理大家都懂,就不介绍了。恰恰这个问题的引入,让我们想到,Lambda表达式的值捕获和形参值传递是一样的,即副本机制;但是Lambda就不能在其

    内部修改呢?这个疑问还得从闭包说起,啥是闭包,请自行Google。简言之,我们在代码中定义Lambda函数时,编译器在编译的时候并不将该Lambda函数直接替换成函数,而是一个对象,注意这里说的是对象;这个对象通过操作符operator()()实现函数的调用,这是不是很熟悉?没错,这就是函数对象。再看如下的代码:

     1 struct unamed1
     2 {
     3     int param;
     4     unamed1(int a) : param(a) {}
     5     void operator()() const {
     6         //param = 10; // Error
     7         std::cout << "param " << param << std::endl;
     8     }
     9 };
    10 
    11 struct unamed2
    12 {
    13     int& param;
    14     unamed2(int& a) : param(a) {}
    15     void operator()() const {
    16         param = 10;  // OK
    17         std::cout << "param " << param << std::endl;
    18     }
    19 };
    20 
    21 struct unamed3
    22 {
    23     int param;
    24     unamed3(int a) : param(a) {}
    25     void operator()(){
    26         param = 10;  // OK
    27         std::cout << "param " << param << std::endl;
    28     }
    29 };

      是不是就”悟“呢?从C++标准草案(http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2011/n3242.pdf)中也可以找到这个问题的答案:

          

      如果我们想对值捕获的变量进行修改,该怎么处理呢?使用mutable修饰。从C++标准文档(https://en.cppreference.com/w/cpp/language/lambda)可以看到如下说明:

      验证如下:

    1 void main()
    2 {
    3     int a = 1, b = 2;
    4 
    5     auto fn = [=]() mutable {a = 10; b = 20; std::cout << "fn(a, b) = " << a + b << "
    "; };
    6     fn();
    7 }

       

       这里需要注意mutable放置的地方哦!!!

  • 相关阅读:
    解决virtualbox与mac文件拖拽问题
    SNMP收集
    scapy的安装
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    subprocess.call(cmd, shell=True)
    能够把意见说的让人接受是个技能
    (转)Jenkins2.0 Pipeline 插件执行持续集成发布流程
    ansible 与 Jinja2的结合 -- 安装zabbix
    运维自动化平台-背后的设计计划和架构
    命令行获取zabbix最新的issues
  • 原文地址:https://www.cnblogs.com/smartNeo/p/14686350.html
Copyright © 2011-2022 走看看