📑 Table of Contents

  1. Lambda Functions in Modern C++ 1.1. Quick overview 1.2. Syntax 1.3. Basic examples 1.4. Capture modes 1.5. Lambda in a Class (Capturing this) 1.6. mutable lambdas 1.7. Generic lambdas (C++14) 1.8. Using lambdas with STL 1.9. std::move capture (C++14/17) 1.10. Storing Lambdas in std::function 1.11. UML-Style Diagram (Conceptual) 1.12. Best practices 1.13. Runnable C++ Examples

🎯 Main Topics Covered

  1. Quick overview
  2. Syntax
  3. Basic examples
  4. Capture modes
  5. Lambda in a Class Capturing this
  6. mutable lambdas
  7. Generic lambdas C14
  8. Using lambdas with STL … and 5 more

Lambda Functions in Modern C++

Lambda functions are essential for writing concise, expressive code — especially with STL algorithms(eg. sort), callbacks, event handeling, threading, and functional patterns.

This guide covers the main concepts, syntax, examples, properties, pitfalls, and best practices.


Quick overview


Syntax

[capture](/learning/programming-language/cpp/lambda-functions/parameters) mutable-exception -> return_type {
    body
};

Basic examples

No Capture

auto say = [](){ std::cout << "Hello\n"; };
say();

With parameters and inferred return

auto add = [](int a, int b) { return a + b; };
std::cout << add(2,3); // 5

With explicit return type

auto div = [](double a, double b) -> double {
    if (b == 0) throw std::runtime_error("div by zero");
    return a / b;
};

Capture modes

Lambda in a Class (Capturing this)

class Test {
public:
    int x = 42;

    void run() {
        auto f = [this]() {
            cout << x;
        };
        f();
    }
};

Example

int a = 1;
int b = 2;

auto valCap = [a]() { return a + 10; };  // uses a copy
auto refCap = [&b]() { b += 5; };        // modifies original b

mutable lambdas

Captured-by-value variables are const inside the lambda by default. mutable makes the captured copy modifiable:

int x = 5;
auto f = [x]() mutable { x += 2; std::cout << x << "\n"; }; // prints 7
f();
std::cout << x << "\n"; // still 5

Generic lambdas (C++14)

Use auto in parameter lists to create templated lambdas:

auto printer = [](auto v){ std::cout << v << "\n"; };
printer(10);
printer("hello");

Using lambdas with STL

std::vector<int> v = {3,1,4,1,5};
std::sort(v.begin(), v.end(), [](int a, int b){ return a < b; });
std::for_each(v.begin(), v.end(), [](int x){ std::cout << x << " "; });

std::move capture (C++14/17)

Capture move-only types (e.g., std::unique_ptr) into a lambda using move-capture:

auto p = std::make_unique<int>(42);
auto lam = [ptr = std::move(p)](){ std::cout << *ptr; }; // ptr moved into lambda

This is essential to capture move-only resources safely.

Storing Lambdas in std::function

std::function<int(int)> square = [](int x){
    return x * x;
};

UML-Style Diagram (Conceptual)

+------------------------------+
|        Lambda Object         |
+------------------------------+
| - capture list (values/refs) |
| - operator() (parameters)    |
+------------------------------+
| + invoked like a function    |
+------------------------------+

Internally, a lambda is a compiler-generated class with:

Example:

[x]() { return x + 1; }

Compiler generates something like:

class __Lambda_1 {
    int x_copy;
public:
    __Lambda_1(int x) : x_copy(x) {}
    int operator()() const { return x_copy + 1; }
};

This explains why capture types matter.

Best practices

Runnable C++ Examples

Full runnable .cpp examples are available here:

👉 For runnable C++ examples, see the accompanying Lambda Examples.

This includes:

Use them to practice and reinforce concepts.