My conclusion is that lambda expressions are not invoked by actually passing captured parameters to the functions [...]
That is correct. The captures work differently from the function parameters of the lambda.
As explained in [expr.prim.lambda.capture] p10, the capture [value]
adds an int
non-static data member to the closure type of the lambda.
You can think of the compiler doing something along the lines of:
// auto print_value = [ value]() { std::cout << value << std::endl; };
struct __lambda {
private:
int value;
void operator()() const { std::cout << value << std::endl; }
};
auto print_value = __lambda{value};
Note: this is not literally what the compiler does, only an approximation.
As seen in the code above, and as stated in [expr.prim.lambda.capture] p15:
When the lambda-expression is evaluated, the entities that are captured by copy are used to direct-initialize each corresponding non-static data member of the resulting closure object, and [...]
Therefore, value
is copied during the initialization of print_value
, before incr_value()
is executed.
incr_value()
changes value
in main
, but by that point, print_value
has its own copy with value 0
, which is printed.