Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to understand lambdas

Tags:

c++

lambda

You captured multiplier by value, which means it was copied into the lambda. You need to capture it by reference:

int multiplier = 5;
auto timesFive = [&multiplier](int a) { return a * multiplier; }; 
std::cout << timesFive(2);

multiplier = 15;
std::cout << timesFive(2); 

Lambdas are syntatic sugar for an unnamable class and the instance thereof. Sometimes expanding your code out to what this unnamable class can help understanding what is going on.

[ capture_list ]( arg_list ) -> return_value_clause_opt { body };

becomes very roughly (pseudo-code):

struct anonymous_type {
  capture_list;
  auto operator()( arg_list ) const -> return_value_clause_opt {
    body
  }
  anonymous_type( capture_list_in ):capture_list(capture_list_in) {}
};

If you list a variable in capture_list by its plain name, it is copied into a copy within the anonymous class.

So your timesFive became

struct __secret_name__ {
  int multiplier;
  int operator()(int a) const { return a*multiplier; }
};
int multiplier = 5;
auto timesFive = __secret_name__{multiplier};

It should be pretty clear that changing multiplier in the above code won't change the behavior of timesFive.

If you put a & in front of the name, a non-const reference is placed within the anonymous class.

struct __secret_name__ {
  int& multiplier;
  int operator()(int a) const { return a*multiplier; }
};
int multiplier = 5;
auto timesFive = __secret_name__{multiplier};

now, changing multiplier will change the behavior of timesFive, because timesFive holds a reference to multiplier, not a copy of it.


Some details skipped above for brevity. The name __secret_name__ is only for exposition. The member variables of the lamba are not actually public. The lambda being trivially constructible is implementation defined even if its data is. Etc.


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!