Lambda Expressions in C++

A lambda expression is a compact way to define an anonymous function (a function without a name) right where it is needed. Introduced in C++11, lambdas make code shorter and more readable — especially when working with STL algorithms.

Basic Syntax

[capture](parameters) -> return_type {
    // function body
}
  • [] — Capture list: which variables from the surrounding scope the lambda can use.
  • () — Parameter list: inputs to the lambda.
  • -> type — Optional return type (often auto-deduced).
  • { } — Lambda body.

Simplest Lambda

#include <iostream>
using namespace std;

int main() {
    auto greet = []() {
        cout << "Hello from lambda!" << endl;
    };

    greet();   // call the lambda
    return 0;
}

Output:

Hello from lambda!

Lambda with Parameters

auto add = [](int a, int b) {
    return a + b;
};

cout << add(3, 7) << endl;   // 10

Lambda with Return Type

auto divide = [](double a, double b) -> double {
    if (b == 0) return 0;
    return a / b;
};

cout << divide(10.0, 4.0) << endl;   // 2.5

Capture List

The capture list allows the lambda to use variables from the enclosing scope:

Capture by value ([=]):

int x = 10;
auto showX = [=]() {
    cout << "x = " << x << endl;   // uses copy of x
};
showX();    // x = 10

Capture by reference ([&]):

int count = 0;
auto increment = [&]() {
    count++;    // modifies the original
};
increment();
increment();
cout << count << endl;   // 2

Capture specific variables:

int a = 5, b = 10;
auto sum = [a, &b]() {
    b += a;    // a by value, b by reference
};
sum();
cout << b << endl;   // 15

Lambda with STL Algorithms

Lambdas shine when used with STL algorithms:

Sorting with custom comparator:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v = {5, 1, 8, 2, 9, 3};

    // Sort in descending order
    sort(v.begin(), v.end(), [](int a, int b) {
        return a > b;
    });

    for (int x : v) cout << x << " ";
    cout << endl;
    return 0;
}

Output:

9 8 5 3 2 1

Using for_each with lambda:

#include <algorithm>
vector<int> nums = {1, 2, 3, 4, 5};
for_each(nums.begin(), nums.end(), [](int n) {
    cout << n * n << " ";
});
// Output: 1 4 9 16 25

Filtering with count_if:

vector<int> data = {10, 25, 30, 45, 50, 15};
int countAbove30 = count_if(data.begin(), data.end(), [](int x) {
    return x > 30;
});
cout << "Elements above 30: " << countAbove30 << endl;   // 2

Mutable Lambda

By default, captured-by-value variables cannot be modified inside the lambda. The mutable keyword allows modification of local copies:

int val = 10;
auto modify = [val]() mutable {
    val += 5;
    cout << "Inside lambda: " << val << endl;   // 15
};
modify();
cout << "Outside: " << val << endl;   // 10 — original unchanged

Generic Lambda (C++14)

In C++14, auto can be used as the parameter type to create generic lambdas:

auto multiply = [](auto a, auto b) {
    return a * b;
};

cout << multiply(3, 4)     << endl;   // 12
cout << multiply(2.5, 4.0) << endl;   // 10.0

Key Takeaways

  • Lambda expressions are anonymous functions defined inline where needed.
  • The capture list [] defines which outer variables are accessible in the lambda.
  • Capture by value [=] copies variables; capture by reference [&] gives direct access.
  • Lambdas work excellently with STL algorithms like sort, for_each, and count_if.
  • Use mutable when needing to modify captured-by-value variables inside the lambda.

Leave a Comment

Your email address will not be published. Required fields are marked *