C++workingcpp17

Lambdas and captures

Inline, anonymous functions that can grab variables from the enclosing scope by value or by reference.

[capture](params){ body } builds a callable on the spot β€” the capture list decides which surrounding variables it sees, mutable lets it keep state, and auto parameters make it generic.

A lambda is an unnamed function you write right where you use it. The full shape is [captures](parameters) -> return { body }, but the return type is usually deduced, so most lambdas read as [captures](params){ body }. You can call it immediately, store it in a variable with auto, or hand it to an algorithm.

The piece unique to lambdas is the capture list in []. An ordinary function only sees its parameters and globals; a lambda can also reach the local variables that exist where it is defined. The capture list names which of those locals it pulls in, and whether it takes a copy or a reference.

Capture by value vs by reference

[x] captures x by value β€” the lambda stores its own copy, frozen at the moment of capture; later changes to the outer x are invisible to it. [&x] captures by reference β€” the lambda refers to the original variable, so it sees later changes and can write back through it. The shorthands [=] and [&] capture every used local by value or by reference respectively, but naming captures explicitly is clearer and safer.

Reference captures come with a lifetime rule: the captured variable must outlive every call to the lambda. Returning a lambda that holds [&local] is a dangling-reference bug. For anything that escapes the current scope, capture by value (or capture a copy via [y = x]).

mutable and generic lambdas

By default a lambda's operator() is const, so value-captured members are read-only inside the body. Marking the lambda mutable drops that const, letting it modify its own captured copies between calls β€” the basis of a tiny stateful counter that remembers a value across invocations without a separate class.

Since C++14, a parameter typed auto makes the lambda generic: the compiler stamps out a call operator for each argument type you use it with, so one lambda works on int, double, std::string, and more. This pairs naturally with the standard algorithms, where lambdas most often appear as comparators and predicates.

Try it 5 examples

Define and call a lambda

C++intro
0ms
2516hello
Reference Β· output compiled offline, not runnable in-browser

square behaves like any callable β€” square(5) is 25 and nesting square(square(2)) squares 4 to 16, while the capture-free greet shows a lambda needs neither parameters nor a capture list.