Skip to content

How to Fix C++ Lambda Capture and Lifetime Errors

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about How to Fix C++ Lambda Capture and Lifetime Errors. We cover key concepts, practical examples, and best practices.

C++ lambda capture errors occur when a lambda captures a local variable by reference and the lambda outlives the variable (dangling reference), or when capture-by-value inadvertently copies a large object or mutable state.

Quick Fix

Wrong

std::function<int()> makeCounter() {
    int count = 0;
    return [&count]() { return ++count; };  // dangling reference!
}

The lambda captures count by reference, but count goes out of scope when makeCounter returns.

std::function<int()> makeCounter() {
    int count = 0;
    return [count]() mutable { return ++count; };  // capture by value
}

auto counter = makeCounter();
std::cout << counter() << " " << counter();
1 2

Fix for mutable lambdas

int val = 42;
auto lambda = [val]() mutable {
    val += 10;
    return val;
};
std::cout << lambda() << " " << val;
52 42

The lambda's copy of val changes, but the original val is unaffected.

Fix for init capture (C++14)

auto lambda = [data = std::move(largeObject)]() {
    // use data
};

Fix for capturing this

struct Widget {
    int value = 42;
    auto getLambda() {
        return [*this]() { return value; };  // C++17: capture copy of *this
    }
};

Prevention

  • Prefer capture-by-value [=] for lambdas that outlive the scope.
  • Use init capture [x = std::move(y)] for move-only types.
  • Capture this by value [*this] (C++17) instead of [this] for async lambdas.
  • Document expected lambda lifetime when capturing by reference.
  • Use std::function sparingly; prefer auto for lambda types.

DodaTech Tools

Doda Browser's C++ lambda lifetime verifier detects dangling reference captures. DodaZIP archives static analysis data. Durga Antivirus Pro detects use-after-free from lambda capture chains.

Common Mistakes with lambda capture

  1. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
  2. Using head and tail instead of pattern matching, causing runtime errors on empty lists
  3. Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks

These mistakes appear frequently in real-world CPP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

What is the difference between capture by reference `[&]` and capture by value `[=]`?

[&] captures all automatic variables by reference (no copies, but can dangle). [=] captures by value (copies, safe but can be expensive). Use [&] for short-lived lambdas, [=] for stored or async lambdas.

How do I capture a move-only type like `unique_ptr` in a lambda?

Use init capture (C++14): [ptr = std::move(myUniquePtr)]() { ... }. This moves the unique_ptr into the lambda's closure.

What is a mutable lambda and when is it needed?

A mutable lambda allows modification of capture-by-value variables. Without mutable, the lambda's operator() is const and cannot modify captured values.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro