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