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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With