I'm reading the C++ Programming Language by B. Stroustrup in its section 11.4.3.4 "mutable Lambdas", which says the following:
Usually, we don’t want to modify the state of the function object (the closure), so by default we can’t. That is, the
operator()()
for the generated function object (§11.4.1) is aconst
member function. In the unlikely event that we want to modify the state (as opposed to modifying the state of some variable captured by reference; §11.4.3), we can declare the lambda mutable.
I don't understand why the default for the operator()()
is const
when the variable is captured by value. What's the rational for this? What could go wrong when I change the value of a variable, which is copied into the function object?
The mutable keyword is used so that the body of the lambda expression can modify its copies of the external variables x and y , which the lambda expression captures by value. Because the lambda expression captures the original variables x and y by value, their values remain 1 after the lambda executes.
Lambda Symbol (λ)
[=] Capture any referenced variable by making a copy. [=, &foo] Capture any referenced variable by making a copy, but capture variable foo by reference. [bar] Capture bar by making a copy; don't copy anything else. [this] Capture the this pointer of the enclosing class.
A lambda expression can refer to identifiers declared outside the lambda expression. If the identifier is a local variable or a reference with automatic storage duration, it is an up-level reference and must be "captured" by the lambda expression.
One can think of lambdas as classes with operator()()
, which by default is defined as const
. That is, it cannot change the state of the object. Consequently, the lambda will behave as a regular function and produce the same result every time it is called. If instead, we declare the lambda as mutable, it is possible for the lambda to modify the internal state of the object, and provide a different result for different calls depending on that state. This is not very intuitive and therefore discouraged.
For example, with mutable lambda, this can happen:
#include <iostream>
int main()
{
int n = 0;
auto lam = [=]() mutable {
n += 1;
return n;
};
std::cout << lam() << "\n"; // Prints 1
std::cout << n << "\n"; // Prints 0
std::cout << lam() << "\n"; // Prints 2
std::cout << n << "\n"; // Prints 0
}
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