zoukankan      html  css  js  c++  java
  • c/c++ lambda 表达式 剖析

    lambda 表达式 剖析

    ## 大前提:捕获列表里变量的确定时机。

    捕获列表和参数列表有区别,捕获列表里的变量,是在捕获的时间点就确定了,而不是在lambda调用时确定,参数列表是在调用时才确定。所以当捕获了一个int i,i=12,然后在lambda后面的代码又改变i为22,但是当调用lambda的时候,i值还是12。

    ## 剖析点:

    1,值捕获,即使在lambda后面改变了该值,在调用lambda时,这个值还是捕获时的值。

    2,引用捕获,在lambda后面改变了该值,在调用lambda时,这个值不是捕获时的值,而是改变后的值。

    3,隐式捕获:

    • [=]代表全部采用值捕获
    • [&]代表全部采用引用捕获
    • [=, &val]代表val为引用捕获,其余为值捕获
    • [&,val]代表val为值捕获,其余为引用捕获

    4,可变lambda,当想在lambda函数体里,修改一个值捕获的变量是,需要mutable关键字。

    5,lambda的返回类型,函数体是单一的return语句的话,可以在声明lambda时,省略返回值的类型。

    ### 由剖析点2:引用捕获,会引发很多血案。比如,被捕获的引用或者指针指向的对象已经不存在了,然后调用lambda时,就会出现致命错误。

    警告:当以引用或者指针方式捕获一个变量时,必须保证在lambda执行时变量是存在的。

    建议:

    1,捕获一个普通变量时,如int, string或其他非指针类型,通常可以采用简单的值捕获方式。所以,只需关注变量在捕获时,值是否是所需的值就行。

    2,如果捕获一个指针或迭代器,或引用,就必须保证在lambda被执行的时候,绑定到迭代器,指针或引用的对象仍然存在,而且,需要保证对象是预期的值。因为,有可能在捕获的时候,是预期的值,但是在执行lambda之前有代码改变了绑定对象的值,在执行lambda时,就变成不是预期的值了。

    3,一般来说,尽量减少捕获的数据量,来避免潜在的捕获导致的问题。而且,如果可能的话,尽量避免捕获指针或引用。

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    int main(){
      //test1 值捕获                                                                
      /*                                                                            
      int i = 1;                                                                    
      auto f = [i]{return i;};                                                      
      i = 10;                                                                       
      int j = f();                                                                  
      cout << j << endl;                                                            
      */
    
      //test2 引用捕获                                                              
      /*                                                                            
      int i = 1;                                                                    
      auto f = [&i]{return i;};                                                     
      i = 10;                                                                       
      int j = f();                                                                  
      cout << j << endl;//3                                                         
      */
    
      //test3 隐式值捕获                                                            
      /*                                                                            
      int i = 1;                                                                    
      int j = 2;                                                                    
      auto f = [=]{return i + j;};                                                  
      i = 3;                                                                        
      int m = f();                                                                  
      cout << m << endl;                                                            
      */
    
      //test4 隐式引用捕获                                                          
      /*                                                                            
      int i = 1;                                                                    
      int j = 2;                                                                    
      auto f = [&]{return i + j;};                                                  
      i = 3;                                                                        
      int m = f();                                                                  
      cout << m << endl;//5                                                         
      */
    
      //test5 隐式,显式混合1                                                       
      /*                                                                            
      int i = 1;                                                                    
      int j = 2;                                                                    
      //i为值捕获,j为引用捕获                                                      
      auto f = [=,&j]{return i + j;};                                               
      i = 3;                                                                        
      int m = f();                                                                  
      cout << m << endl;//3                                                         
      */
    
      //test5 隐式,显式混合2                                                       
      /*                                                                            
      int i = 1;                                                                    
      int j = 2;                                                                    
      //i为引用捕获,j为值捕获                                                      
      auto f = [&,j]{return i + j;};                                                
      i = 3;                                                                        
      int m = f();                                                                  
      cout << m << endl;//5                                                         
      */
    
      //test6 可变lambda                                                            
      /*                                                                            
      int i = 10;                                                                   
      auto f = [i] () mutable{return ++i;};                                         
      int j = f();                                                                  
      cout << j << endl;                                                            
      */
      /*                                                                            
      const int i = 10;                                                             
      //编译错误,因为i为const                                                      
      auto f = [i] () mutable{return ++i;};                                         
      int j = f();                                                                  
      cout << j << endl;                                                            
      */
    
      //test7 lambda的返回类型                                                      
      vector<int> ivec{-12,2,-22,3,0};
      //改变ivec里的值,负数变成整数                                                
      //此lambda不写返回类型没有问题.                                               
      //transform(ivec.begin(),ivec.end(),ivec.begin(),                             
      //        [](int i){return i < 0 ? -i : i;});                                 
      //此lambda不写返回类型也没有问题.                                             
      transform(ivec.begin(),ivec.end(),ivec.begin(),
                [](int i){if(i < 0) return -i;
                  else return i;});
      for(const auto &s : ivec){
        cout << s << " ";
      }
      cout << endl;
    }
    

    c/c++ 学习互助QQ群:877684253

    本人微信:xiaoshitou5854

  • 相关阅读:
    Linux环境下入侵工具Knark的分析及防范 java程序员
    六个步骤即可防范ARP地址欺骗类病毒 java程序员
    巧用命令行 揪出ARP欺骗病毒母机方法 java程序员
    poj3264Balanced Lineup(线段树RMQ)
    有了1A的把握再去提交
    poj2828Buy Tickets(线段树 单点更新+区间求和+区间第K值)
    poj2513Colored Sticks(无向图判欧拉路、回路+trie树)
    ACM数学(转)
    sdut2381Broken Keyboard
    sdut2383Decode the Strings(循环节)
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/9672516.html
Copyright © 2011-2022 走看看