Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. C++ Dictionary
  3. lambda

lambda

C++ lambda expressions, introduced in C++11, define anonymous functions inline. Their key feature is the capture list, which takes variables from the enclosing scope by value or by reference. Lambdas combine especially well with STL algorithms.

Syntax

// [capture list](parameters) -> return type { body }
// Return type can be omitted; the compiler infers it.

// Simplest lambda: no captures
auto greet = []() {
    // body
};

// Lambda with parameters
auto add = [](int a, int b) -> int {
    return a + b;
};

// Return type omitted — compiler infers it
auto multiply = [](int a, int b) {
    return a * b;
};

// Value capture: takes a copy of x
int x = 10;
auto printX = [x]() {
    // changes to the external x do not affect this copy
};

// Reference capture: holds a reference to counter
int counter = 0;
auto increment = [&counter]() {
    counter++;  // modifies the external counter directly
};

// [=] captures all variables by value; [&] by reference
auto captureAll = [=]() { /* copy of all outer variables */ };
auto captureRef = [&]() { /* reference to all outer variables */ };

// mutable: allows modifying the captured copy inside the lambda
auto mutableLambda = [x]() mutable {
    x++;  // only the copy changes; external x is unchanged
};

Capture Reference

Capture NotationDescription
[]Captures nothing. For lambdas that use no external variables.
[x]Captures x by value (copy). Changes inside the lambda do not affect the original.
[&x]Captures x by reference. Changes inside the lambda directly affect the original.
[=]Captures all variables in scope by value.
[&]Captures all variables in scope by reference.
[=, &x]Default value capture, but x is captured by reference.
[&, x]Default reference capture, but x is captured by value.
mutableAllows modifying the value-captured copy inside the lambda body. External variables are unchanged.

Sample Code

kiryu_lambda.cpp
// kiryu_lambda.cpp
// Lambda expression sample using Yakuza (Like a Dragon) characters.
// Demonstrates capture types and use with STL algorithms.

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

struct Character {
    std::string name;
    std::string role;
    int heat;
};

int main() {
    // 1. No capture: simple separator lambda
    auto printSeparator = []() {
        std::cout << "==============================" << std::endl;
    };

    printSeparator();
    std::cout << "Yakuza Lambda Sample" << std::endl;
    printSeparator();

    // 2. Value capture: takes a copy of protagonist and baseHeat
    std::string protagonist = "Kiryu Kazuma";
    int baseHeat = 50;

    auto showHero = [protagonist, baseHeat]() {
        std::cout << "Protagonist: " << protagonist
                  << "  Base Heat: " << baseHeat << std::endl;
    };

    showHero();
    baseHeat = 999;
    std::cout << "Even after changing baseHeat, the captured copy is unchanged:" << std::endl;
    showHero();  // still shows 50

    printSeparator();

    // 3. Reference capture: modifies totalBattles directly
    int totalBattles = 0;
    auto recordBattle = [&totalBattles](const std::string& winner) {
        totalBattles++;
        std::cout << "Battle #" << totalBattles << " winner: " << winner << std::endl;
    };

    recordBattle("Kiryu Kazuma");
    recordBattle("Majima Goro");
    recordBattle("Nishikiyama Akira");
    std::cout << "Total battles (updated via reference): " << totalBattles << std::endl;

    printSeparator();

    // 4. Lambda as comparator for std::sort
    std::vector<Character> characters;
    characters.push_back({"Kiryu Kazuma",    "Protagonist",    90});
    characters.push_back({"Majima Goro",     "Mad Dog",        95});
    characters.push_back({"Shimano Futoshi", "Executive",      70});
    characters.push_back({"Nishida Junichi", "Sub-boss",       65});
    characters.push_back({"Nishikiyama Akira", "Kiryu's brother", 80});

    std::sort(characters.begin(), characters.end(),
        [](const Character& a, const Character& b) {
            return a.heat > b.heat;  // descending
        }
    );

    std::cout << "--- Heat Gauge (descending) ---" << std::endl;
    for (int i = 0; i < (int)characters.size(); i++) {
        std::cout << characters[i].name << " (" << characters[i].role << ")"
                  << "  Heat: " << characters[i].heat << std::endl;
    }

    printSeparator();

    // 5. Lambda as predicate for std::find_if
    int threshold = 85;
    auto it = std::find_if(characters.begin(), characters.end(),
        [threshold](const Character& c) {
            return c.heat >= threshold;
        }
    );

    if (it != characters.end()) {
        std::cout << "First character with heat >= " << threshold << ": "
                  << it->name << " (heat: " << it->heat << ")" << std::endl;
    }

    printSeparator();

    // 6. mutable: allows modifying the value-captured copy
    int heatLevel = 0;
    auto chargeHeat = [heatLevel]() mutable {
        heatLevel += 10;
        std::cout << "Charging… internal heatLevel: " << heatLevel << std::endl;
    };

    chargeHeat();
    chargeHeat();
    chargeHeat();
    std::cout << "External heatLevel is unchanged: " << heatLevel << std::endl;

    printSeparator();

    // 7. Lambda returning a lambda (closure)
    auto makeHeatBooster = [](int bonus) {
        return [bonus](const Character& c) {
            std::cout << c.name << " heat: " << c.heat
                      << " → " << c.heat + bonus << " (+" << bonus << ")" << std::endl;
        };
    };

    auto boostBy20 = makeHeatBooster(20);
    std::cout << "--- Heat Boost (+20) ---" << std::endl;
    boostBy20(characters[0]);
    boostBy20(characters[1]);

    printSeparator();

    return 0;
}
g++ -std=c++11 kiryu_lambda.cpp -o kiryu_lambda
./kiryu_lambda
==============================
Yakuza Lambda Sample
==============================
Protagonist: Kiryu Kazuma  Base Heat: 50
Even after changing baseHeat, the captured copy is unchanged:
Protagonist: Kiryu Kazuma  Base Heat: 50
==============================
Battle #1 winner: Kiryu Kazuma
Battle #2 winner: Majima Goro
Battle #3 winner: Nishikiyama Akira
Total battles (updated via reference): 3
==============================
--- Heat Gauge (descending) ---
Majima Goro (Mad Dog)  Heat: 95
Kiryu Kazuma (Protagonist)  Heat: 90
Nishikiyama Akira (Kiryu's brother)  Heat: 80
Shimano Futoshi (Executive)  Heat: 70
Nishida Junichi (Sub-boss)  Heat: 65
==============================
First character with heat >= 85: Majima Goro (heat: 95)
==============================
Charging… internal heatLevel: 10
Charging… internal heatLevel: 20
Charging… internal heatLevel: 30
External heatLevel is unchanged: 0
==============================
--- Heat Boost (+20) ---
Majima Goro heat: 95 → 115 (+20)
Kiryu Kazuma heat: 90 → 110 (+20)
==============================

Common Mistake 1: Reference-captured local variable goes out of scope

A reference capture ([&x]) holds a reference to a local variable. If the variable's lifetime ends before the lambda is called, the reference is dangling — accessing it is undefined behavior. When a lambda outlives the captured variable, use value capture instead.

// NG: name is destroyed when makeLambda returns
auto makeLambda = []() {
    std::string name = "Majima Goro";
    return [&name]() {          // captures a reference to name
        std::cout << name << std::endl;
    };
};

auto lambda = makeLambda();
lambda();  // undefined behavior: name no longer exists

OK: capture by value so a copy of name survives inside the lambda.

// OK:
auto makeLambda = []() {
    std::string name = "Majima Goro";
    return [name]() {           // copy is stored inside the lambda
        std::cout << name << std::endl;
    };
};

auto lambda = makeLambda();
lambda();  // prints "Majima Goro"

Common Mistake 2: Modifying a value-captured variable without mutable

A value-captured variable is const by default inside the lambda body. Trying to modify it without mutable is a compile error.

// NG: compile error — value-captured variable is const
int heatLevel = 0;
auto charge = [heatLevel]() {
    heatLevel++;  // error: assignment to const
};

OK: add mutable to allow modifying the captured copy.

// OK:
auto charge = [heatLevel]() mutable {
    heatLevel++;  // modifies the copy; external heatLevel unchanged
};

Overview

Lambda expressions, introduced in C++11, are written as [capture](params) -> return_type { body }. The capture list is their defining feature: [x] copies the variable, [&x] holds a reference. [=] copies all outer variables; [&] references all of them. To modify a value-captured variable inside the lambda, add mutable; only the copy is changed — the original is unaffected. Lambdas are particularly powerful in combination with STL algorithms such as std::sort() and std::find_if(). A lambda that returns another lambda acts as a closure, generating functions with specific parameters baked in. The return type can usually be omitted because the compiler infers it.

If you find any errors or copyright issues, please .