Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I change the value of a variable captured by copy in a lambda function?

Tags:

c++

lambda

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 a const 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?

like image 855
François-Marie Arouet Avatar asked Mar 30 '17 21:03

François-Marie Arouet


People also ask

What is mutable in lambda?

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.

How do you write lambda in copy?

Lambda Symbol (λ)

How do you pass a variable in lambda expression?

[=] 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.

What is capture in lambda function?

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.


1 Answers

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
}
like image 185
Andrzej Pronobis Avatar answered Oct 20 '22 04:10

Andrzej Pronobis