Lambda expressions in C++ are a powerful feature that allow you to define anonymous functions directly within your code. They provide a concise way to represent and pass functions, especially useful for short snippets of code that are not reused elsewhere. This guide will cover the basics, syntax, and advanced use cases of C++ Lambda Expressions.
Lambda expressions simplify function usage and creation by enabling inline function definitions. They are particularly useful in situations where you need to pass a function as an argument or use a function for a short period within a particular scope.
Basic Syntax of lambda expression:
[capture](parameters) -> return_type {
// function body
};
- Capture: Specifies which variables from the surrounding scope are captured and how.
- Parameters: List of parameters just like in a regular function.
- Return type: Optional, deduced if omitted.
- Function body: The code to be executed.
Capturing Variables
1. Capturing by Value
Capturing by value means the lambda gets a copy of the variable.
int x = 10;
auto lambda = [x]() {
// x is captured by value
std::cout << "Captured x: " << x << std::endl;
};
lambda();
2. Capturing by Reference
Capturing by reference means the lambda refers to the original variable.
int x = 10;
auto lambda = [&x]() {
// x is captured by reference
x += 5;
std::cout << "Captured x by reference: " << x << std::endl;
};
lambda();
3. Capturing All Variables
- By value:
[=]
- By reference:
[&]
int a = 5, b = 10;
auto lambda = [=]() {
std::cout << "Captured by value a: " << a << ", b: " << b << std::endl;
};
lambda();
Examples:
- Adding two integers:
#include <iostream>
int main() {
auto add = [](int a, int b) -> int {
return a + b;
};
std::cout << "Sum: " << add(3, 4) << std::endl;
return 0;
}
2. Sorting with Lambdas:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {5, 3, 2, 8, 1};
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a < b;
});
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
3. Filtering:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {5, 3, 2, 8, 1};
auto it = std::remove_if(numbers.begin(), numbers.end(), [](int x) {
return x % 2 == 0;
});
numbers.erase(it, numbers.end());
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
Advanced Features:
Mutable Lambdas
By default, lambdas cannot modify captured variables. To allow modification, use the mutable
keyword.
int x = 10;
auto lambda = [x]() mutable {
x += 5;
std::cout << "Mutable lambda x: " << x << std::endl;
};
lambda();
std::cout << "Original x: " << x << std::endl;
Generic Lambdas
With C++14, lambdas can be templated using auto parameters.
auto lambda = [](auto a, auto b) {
return a + b;
};
std::cout << lambda(3, 4) << std::endl;
std::cout << lambda(3.5, 4.5) << std::endl;
Conclusion
C++ Lambda Expressions are a versatile and powerful feature that can greatly enhance the flexibility and readability of your code. From simplifying function calls and event handling to enabling more concise parallel programming, lambdas are an essential tool in modern C++ programming. By understanding their syntax, capturing mechanisms, and advanced features, you can leverage lambdas to write more efficient and maintainable code.