C++ Lambda Expressions

Anonymous functions for modern C++ programming

🚀 What are Lambda Expressions?

Lambda expressions are anonymous functions that you can define inline. They're perfect for short, simple functions that you use once, making your code cleaner and more readable.


// Simple lambda that adds two numbers
auto add = [](int a, int b) { return a + b; };
int result = add(5, 3);  // result = 8
                                    

Output:

result = 8

Lambda Components

📦

Capture Clause

How lambda accesses outside variables

[x, &y]  // x by value, y by reference
📝

Parameters

Input parameters like regular functions

(int a, int b)  // Two integer parameters
🔄

Return Type

Optional explicit return type

-> int { return a + b; }

Function Body

The actual code that executes

{ return a * 2; }

🔹 Basic Lambda Syntax

Lambda expressions define anonymous functions inline using the syntax [capture](parameters) { body }. They allow quick function objects for short-lived operations, like auto greet = []() { cout << "Hello"; };. Lambdas are concise, avoid formal function declarations, and are ideal for callbacks, STL algorithms, or localized logic. They capture variables from scope, support mutable specs, and can be assigned to auto or std::function, enhancing modern C++ expressiveness and functional programming styles.

#include <iostream>
using namespace std;

int main() {
    // Basic lambda with no capture
    auto greet = []() { 
        cout << "Hello from lambda!" << endl; 
    };
    
    // Lambda with parameters
    auto multiply = [](int x, int y) { 
        return x * y; 
    };
    
    // Call the lambdas
    greet();
    cout << "5 * 3 = " << multiply(5, 3) << endl;
    
    return 0;
}

Output:

Hello from lambda!
5 * 3 = 15

🔹 Capture Modes

Lambda capture modes determine how external variables are accessed: by value [=], by reference [&], or individually. For example, [x] captures x by value, [&y] by reference. Captures enable lambdas to use surrounding context, making them powerful for closures. Proper use avoids dangling references, manages lifetimes, and supports stateful anonymous functions. Capture modes are essential for integrating lambdas with existing variables, commonly in event handling, threading, or algorithm customizations in C++.

#include <iostream>
using namespace std;

int main() {
    int x = 10, y = 20;
    
    // Capture by value
    auto lambda1 = [x]() { 
        cout << "x = " << x << endl; 
    };
    
    // Capture by reference
    auto lambda2 = [&y]() { 
        y += 5;  // Modifies original y
        cout << "y = " << y << endl; 
    };
    
    // Capture all by value
    auto lambda3 = [=]() { 
        cout << "x + y = " << x + y << endl; 
    };
    
    lambda1();
    lambda2();
    lambda3();
    
    return 0;
}

Output:

x = 10
y = 25
x + y = 35

🔹 Lambda with STL Algorithms

Lambdas excel with STL algorithms like std::for_each, std::transform, or std::count_if to provide custom predicates or operations inline. For example, count_if(vec.begin(), vec.end(), [](int n){ return n%2==0; }) counts evens. This eliminates the need for separate function objects, keeps logic local, and improves code readability. Lambdas with STL promote a functional style, simplify complex iterations, and are a hallmark of modern C++ programming for data processing, filtering, and transformations.

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

int main() {
    vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // Count even numbers using lambda
    int evenCount = count_if(numbers.begin(), numbers.end(), 
                             [](int n) { return n % 2 == 0; });
    
    // Transform all numbers (multiply by 2)
    transform(numbers.begin(), numbers.end(), numbers.begin(),
              [](int n) { return n * 2; });
    
    cout << "Even numbers: " << evenCount << endl;
    cout << "Doubled: ";
    for (int n : numbers) cout << n << " ";
    
    return 0;
}

Output:

Even numbers: 5
Doubled: 2 4 6 8 10 12 14 16 18 20

🧠 Test Your Knowledge

What does [&] mean in a lambda capture clause?