Analysis of c/c++ lambda expression

Keywords: C++ Lambda REST

Analysis of lambda expression

Big premise: capture the timing of variables in the list.

There is a difference between the capture list and the parameter list. The variables in the capture list are determined at the time of capture, not at the time of lambda call. The parameter list is determined at the time of call. So when I capture an int i, i=12, and then the code after lambda changes I to 22, but when I call lambda, I is still 12.

Analysis points:

1. Value capture. Even if the value is changed after the lambda, when calling the lambda, the value is still the value at capture time.

2. Reference capture. The value is changed after lambda. When calling lambda, the value is not the value at capture time, but the value after change.

3. Implicit capture:

  • [=] for all adopted value capture
  • [&] for all reference capture
  • [=, & val] means val is a reference capture and the rest is a value capture
  • [&, val] means val is value capture, the rest is reference capture

4. Variable lambda. When you want to modify a value capture variable in the body of a lambda function, you need the mutable keyword.

5. If the return type of lambda is a single return statement, the return value type can be omitted when declaring lambda.

Captured by dissecting point 2: reference, many murders will be caused. For example, the object that the captured reference or pointer points to does not exist, and then a fatal error occurs when calling lambda.


Warning: when capturing a variable by reference or pointer, you must ensure that the variable exists when the lambda executes.

Recommendation:

1. When capturing a common variable, such as int, string or other non pointer types, you can usually use a simple value capture method. Therefore, you only need to pay attention to whether the value is the required value when the variable is captured.

2. If you capture a pointer or iterator or reference, you must ensure that when the lambda is executed, the object bound to the iterator, the pointer or reference still exists, and you need to ensure that the object is the expected value. Because, it is possible that when capturing, it is the expected value, but before executing the lambda, some code changes the value of the bound object, and when executing the lambda, it becomes the unexpected value.

3. Generally speaking, minimize the amount of data captured to avoid potential problems caused by capture. Also, try to avoid catching pointers or references if possible.

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main(){
  //test1 value capture                                                                
  /*                                                                            
  int i = 1;                                                                    
  auto f = [i]{return i;};                                                      
  i = 10;                                                                       
  int j = f();                                                                  
  cout << j << endl;                                                            
  */

  //test2 reference capture                                                              
  /*                                                                            
  int i = 1;                                                                    
  auto f = [&i]{return i;};                                                     
  i = 10;                                                                       
  int j = f();                                                                  
  cout << j << endl;//3                                                         
  */

  //test3 implicit value capture                                                            
  /*                                                                            
  int i = 1;                                                                    
  int j = 2;                                                                    
  auto f = [=]{return i + j;};                                                  
  i = 3;                                                                        
  int m = f();                                                                  
  cout << m << endl;                                                            
  */

  //test4 implicit reference capture                                                          
  /*                                                                            
  int i = 1;                                                                    
  int j = 2;                                                                    
  auto f = [&]{return i + j;};                                                  
  i = 3;                                                                        
  int m = f();                                                                  
  cout << m << endl;//5                                                         
  */

  //test5 implicit, explicit mix 1                                                       
  /*                                                                            
  int i = 1;                                                                    
  int j = 2;                                                                    
  //i Capture for value, j capture for reference                                                      
  auto f = [=,&j]{return i + j;};                                               
  i = 3;                                                                        
  int m = f();                                                                  
  cout << m << endl;//3                                                         
  */

  //test5 implicit, explicit mix 2                                                       
  /*                                                                            
  int i = 1;                                                                    
  int j = 2;                                                                    
  //i Capture for reference, j for value                                                      
  auto f = [&,j]{return i + j;};                                                
  i = 3;                                                                        
  int m = f();                                                                  
  cout << m << endl;//5                                                         
  */

  //test6 variable lambda                                                            
  /*                                                                            
  int i = 10;                                                                   
  auto f = [i] () mutable{return ++i;};                                         
  int j = f();                                                                  
  cout << j << endl;                                                            
  */
  /*                                                                            
  const int i = 10;                                                             
  //Compile error because i is const                                                      
  auto f = [i] () mutable{return ++i;};                                         
  int j = f();                                                                  
  cout << j << endl;                                                            
  */

  //Return type of test7 lambda                                                      
  vector<int> ivec{-12,2,-22,3,0};
  //Change the value in ivec, negative number becomes integer                                                
  //There is no problem for this lambda not to write the return type                                               
  //transform(ivec.begin(),ivec.end(),ivec.begin(),                             
  //        [](int i){return i < 0 ? -i : i;});                                 
  //There is no problem for this lambda not to write the return type                                             
  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;
}

QQ group of mutual learning in c/c + +: 877684253

My wechat: xiaoshitou5854

Posted by markmil2002 on Mon, 30 Dec 2019 12:14:05 -0800