zoukankan      html  css  js  c++  java
  • lambda续集——2

    隐式捕获:

    出了显式列出我们希望使用的来自函数的变量外,还可以让编译器根据lambda体中的代码来推断我们要使用哪些变量。为了指示编译器推断捕获列表,应在捕获列表中写一个&或=。&告诉编译器采用引用捕获方式,=告诉编译器采用值捕获方式。我们可以混合使用隐式或显式捕获,在此条件下,捕获列表的第一个元素必须是一个&或=。当混合使用隐式和显式捕获时,显式捕获的变量必须使用与隐式捕获不同的方式。即,如果隐式捕获时引用(&)方式,则显式捕获名变量必须使用值捕获方式,因此不能在显式捕获名字前使用&;如果是隐式捕获时值(=)方式,显式捕获变量名必须采用引用方式,即在名字前加&。

    eg:

     1 #include<iostream>
     2 using namespace std;
     3 
     4 int main()
     5 {
     6     /*隐式引用捕获*/
     7     int ma = 10;
     8     int mma = 10;
     9     auto f= [&] {return ma+mma; };
    10     ma = 1;
    11     cout << f() << endl;
    12 
    13     /*隐式值捕获*/
    14     int a = 10;
    15     int aa = 10;
    16     auto ff = [=] {return a+aa; };
    17     a = 1;
    18     cout << ff() << endl;
    19 
    20     /*混合捕获,引用在前*/
    21     int i = 10;
    22     int j = 100;
    23     auto fff = [&,j] {return i+j; };
    24     //auto fff = [&i, =] {return i + j; }; err
    25     //auto fff = [&i, &] {return i + j; }; err
    26     i = 1;
    27     cout << fff() << endl;
    28 
    29     /*混合捕获,值在前*/
    30     int m = 10;
    31     int n = 100;
    32     auto ffff = [=, &n] {return m + n; };
    33     n = 1;
    34     cout << ffff() << endl;
    35 
    36     /*混合捕获的思考,多个变量,可以隐式捕获,针对特殊变量,单独指定*/
    37     int q = 1, w = 10, e = 20, r = 30;
    38     /*我想除了e变量,其余的都用值捕获*/
    39     auto fffff = [=, &e] {return q+w+e+r; };
    40     e = 100;
    41     cout << fffff() << endl;
    42     return 0;
    43 }

    可变lambda:

    默认情况下,对于一个值拷贝的变量,lambda不会改变其值,如果我们希望能改变一个被捕获的变量的值,就必须在参数列表后加上mutable。因此,可变lambda能省略参数列表。

     1 #include<iostream>
     2 using namespace std;
     3 
     4 int main()
     5 {
     6     int ma = 10;
     7     auto f= [=] ()mutable {return ++ma; };
     8     cout << f() << endl;
     9     return 0;
    10 }

    一个引用捕获能否改变变量的值依赖于此引用指向的是一个const类型还是一个非const类型。

    指定lambda返回类型:

    默认情况下,如果lambda体包含return之外的任何语句,则编译器假定此lambda返回void。与其他返回void的函数类似,被推断返回void的lambda不能返回值。

    1 #include<iostream>
    2 using namespace std;
    3 
    4 int main()
    5 {
    6     auto f = [](int* a)->int * { if (*a > 0)return a; else return NULL; };
    7     cout << f(NULL) << endl;
    8     return 0;
    9 }

    不用位置返回类型将报错。但是如果返回类型都是一种类型,比如上诉两个return,都return一种类型,是可以推断的,但是吐过return类型不同,将要使用尾置返回类型强制指定,在不止单纯一条return语句时,建议最好使用尾置返回类型。

    对于那种只在一两个地方使用的简单操作,lambda表达式是很有用的。但如果我们需要在很多地方使用相同的操作,通常应该定义一个函数,而不是多次编写相同的lambda表达式。类似的,如果一个操作需要很多语句完成,通常使用函数更好。如果一个lambda捕获列表为空,通常可以用函数来代替它。但是对于捕获局部变量的lambda,用函数替代就不那么容易了。

  • 相关阅读:
    【并发编程】安全发布对象
    【并发编程】并发的学习步骤
    特殊字符
    【并发编程】【JDK源码】CAS与synchronized
    【并发编程】【JDK源码】JDK的(J.U.C)java.util.concurrent包结构
    【JDK源码】将JDK源码导入IDEA中
    【Linux命令】用户及分用户组
    【Linux命令】linux一次性解压多个.gz或者.tar.gz文件
    悟透JavaScript
    设计模式------工厂模式和抽象工厂模式
  • 原文地址:https://www.cnblogs.com/yangguang-it/p/6609800.html
Copyright © 2011-2022 走看看