Skip to main content
A mutable lambda in C++ is an anonymous function object that allows the modification of variables captured by value. By default, the compiler-generated function call operator (operator()) of a lambda expression is const-qualified, making by-value captures read-only. Appending the mutable keyword removes this const qualification, enabling the lambda’s body to mutate its internal state (the copied variables) without affecting the original variables in the enclosing scope.

Syntax

The mutable specifier is placed after the parameter list and before the trailing return type (if specified) or the function body.
Parameter List Omission (C++23 vs. Older Standards): In C++11 through C++20, if the mutable specifier is used, the parameter list () is strictly mandatory, even if the lambda accepts no arguments. As of C++23 (via proposal P1102R2), the empty parameter list () is optional when using mutable or other specifiers.

Under the Hood: The Closure Object

To understand mutable, you must examine the compiler-generated class (the closure type) created for the lambda.

Default Lambda (Non-Mutable)

When you capture a variable by value without mutable:
The compiler generates a class roughly equivalent to this:

Mutable Lambda

When you apply the mutable keyword:
The compiler generates a class where the const qualifier is stripped from the operator():

Technical Characteristics and Edge Cases

  1. State Persistence: Because mutable modifies the member variables of the closure object itself, the mutated state persists across multiple invocations of the same lambda instance.
  1. Isolation from Enclosing Scope: Mutating a by-value capture only alters the closure object’s internal copy. The original variable in the enclosing scope remains completely unchanged.
  2. Top-Level const Variables: If a variable is declared with a top-level const in the enclosing scope, capturing it by value copies the const qualifier directly to the closure’s internal data member. In this scenario, applying mutable strips the const from operator(), but the internal variable itself remains a const type and cannot be modified.
  1. Irrelevance to Reference Captures: The mutable keyword has no practical effect on variables captured by reference ([&], [&x]). A reference capture allows modification of the original variable regardless of whether the lambda is mutable, because the const qualification of the default operator() applies to the reference itself (which is inherently immutable in what it points to), not the referenced data.
Tired of Poor C++ Skills? Fix That With Deep Grasping!Learn More