Lambda expressions in C++ are a powerful feature that allows you to create anonymous functions, also known as closures, on the fly. They are particularly useful in situations where you need to pass a small function as an argument to another function, or when you want to define a function-like behavior inline without the need to formally define a named function.
The basic syntax of a lambda expression is:
[capture list](parameters) -> return type {
// Function body
};
#include <iostream>
int main() {
auto greet = []() {
std::cout << "Hello, World!" << std::endl;
};
greet(); // Calls the lambda and prints "Hello, World!"
return 0;
}
auto greet = []() { ... };
defines a lambda expression that takes no parameters and returns void.
The greet
variable now holds this lambda.#include <iostream>
int main() {
auto add = [](int a, int b) -> int {
return a + b;
};
int result = add(3, 4); // Calls the lambda with arguments 3 and 4
std::cout << "Result: " << result << std::endl; // Outputs: Result: 7
return 0;
}
auto add = [](int a, int b) -> int { ... };
defines a lambda that takes two int parameters and returns their sum.int
is explicitly specified, but it could be omitted because the compiler can deduce it from the return statement.The capture list allows the lambda to access variables from the surrounding scope.
#include <iostream>
int main() {
int x = 10;
auto printX = [x]() {
std::cout << "x = " << x << std::endl;
};
x = 20;
printX(); // Outputs: x = 10 (captured value of x)
return 0;
}
[x]
captures the variable x
by value, meaning the lambda captures and stores the value of x
at the time the lambda is created. Changes to x
after the lambda is created do not affect the captured value.
&
): #include <iostream>
int main() {
int x = 10;
auto printX = [&x]() {
std::cout << "x = " << x << std::endl;
};
x = 20;
printX(); // Outputs: x = 20 (captured reference to x)
return 0;
}
[&x]
captures x
by reference, meaning the lambda captures the memory address of x
,
so any changes to x
after the lambda is created are reflected when the lambda is executed.
You can also capture all variables in the surrounding scope by value or by reference.
#include <iostream>
int main() {
int x = 10;
int y = 20;
auto printXY = [=]() {
std::cout << "x = " << x << ", y = " << y << std::endl;
};
auto modifyXY = [&]() {
x += 10;
y += 10;
};
printXY(); // Outputs: x = 10, y = 20
modifyXY();
printXY(); // Still outputs: x = 10, y = 20 because the lambda captures by value
return 0;
}
[=]
captures all variables by value. In printXY, x and y are captured by value, so changes to x and y after the lambda is created do not affect the captured values.[&]
captures all variables by reference. In modifyXY, x and y are captured by reference, so changes to x and y within the lambda affect the original variables.A lambda can return a value, just like a regular function.
#include <iostream>
int main() {
int x = 5;
int y = 10;
auto maxVal = [](int a, int b) {
return (a > b) ? a : b;
};
std::cout << "Max value: " << maxVal(x, y) << std::endl; // Outputs: Max value: 10
return 0;
}
Lambdas are often used with standard algorithms like std::sort, std::for_each, etc.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {1, 3, 2, 5, 4};
// Sort in descending order using a lambda
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a > b;
});
// Print sorted numbers
std::for_each(numbers.begin(), numbers.end(), [](int n) {
std::cout << n << " ";
});
std::cout << std::endl; // Outputs: 5 4 3 2 1
return 0;
}
std::sort
sorts the vector in descending order.std::for_each
prints each element in the sorted vector.