简体   繁体   中英

C++11 lambda capture by value captures at declaration point

The code below prints 0, but I expect to see a 1. My conclusion is that lambda functions are not invoked by actually passing captured parameters to the functions, which is more intuitive. Am I right or am I missing something?

#include <iostream>
int main(int argc, char **argv){
  int value = 0;
  auto incr_value  = [&value]() { value++; };
  auto print_value = [ value]() { std::cout << value << std::endl; };
  incr_value();
  print_value();
  return 0;
}

Lambda functions are invoked by actually passing captured parameters to the function.

value is equal to 0 at the point where the lambda is defined (and value is captured). Since you are capturing by value, it doesn't matter what you do to value after the capture.

If you had captured value by reference, then you would see a 1 printed because even though the point of capture is still the same (the lambda definition) you would be printing the current value of the captured object and not a copy of it created when it was captured.

Yes, the captures are done at the point the lambda is declared, not when it's called. Think of a lambda as a function object whose constructor takes the captured variables as parameters and assigns them to its corresponding member variables (either values or references, depending on the capture mode.) The actual call of the lambda has no magic, it's just a regular operator() call of the underlying function object.

Capturing things at the call point would not make much sense - what would be captured if the lambda was returned or passed as a parameter to another function and called there? There are actually languages that do behave this way - if you refer to a variable x in a function, it is assumed to refer to any variable called x currently in scope at the point of call. This is called dynamic scoping. The alternative, used by most languages because it makes reasoning about programs much simpler, is called lexical scoping.

http://en.wikipedia.org/wiki/Lexical_scoping#Lexical_scoping_and_dynamic_scoping

The problem is that your print function is capturing by value and not by reference.

#include <iostream>
int main(int argc, char **argv){
  int value = 0;
  auto incr_value  = [&value]() { value++; };
  auto print_value = [ value]() { std::cout << value << std::endl; };
  auto print_valueref = [ &value]() { std::cout << value << std::endl; };

  incr_value();
  print_value();
  print_valueref();
  return 0;
}

Outputs 0 and 1 as expected. The first one is captured by value and prints the value at the point of capture; the second one captures the reference and then prints its value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM