In C++, a lambda function is a compact syntax for defining anonymous functions, without the need to declare it explicitly as a traditional function.
These functions are especially useful for simple and quick operations. For example, when dealing with operations on collections, such as filtering, mapping, or reducing.
If you want to learn more, check out the Introduction to Programming Course
Lambda Function Syntax
The basic syntax of a lambda function in C++ is as follows:
[capture](parameters) -> return_type { body }
- Capture: List of variables from the environment that the lambda can use.
- Parameters: List of input parameters, separated by commas if there is more than one.
- Return type: Type of value returned by the lambda, optional if the type is deducible.
- Body: The code that executes when the lambda is invoked.
Basic Example
Here is a basic example of a lambda function that adds two numbers:
#include <iostream>
int main() {
auto add = [](int x, int y) -> int {
return x + y;
};
std::cout << "Sum: " << add(5, 3) << std::endl; // Output: 8
return 0;
}
In this example,
- The lambda function
addtakes two parametersxandy, and returns their sum. - The keyword
autois used to deduce the type of the lambda, and-> intspecifies the return type.
Variable Capture
Lambda functions can capture variables from the context in which they are defined. There are different capture modes:
- By value (
=): Captures a copy of the variables. - By reference (
&): Captures variables by reference, allowing modification of their value. - Mixed: Combination of captures by value and by reference.
#include <iostream>
int main() {
int value = 10;
auto lambda = [value]() {
std::cout << "Value: " << value << std::endl;
};
lambda(); // Output: Value: 10
return 0;
}
#include <iostream>
int main() {
int value = 10;
auto lambda = [&value]() {
value++;
std::cout << "Value: " << value << std::endl;
};
lambda(); // Output: Value: 11
std::cout << "Value after lambda: " << value << std::endl; // Output: Value after lambda: 11
return 0;
}
Use in Higher-Order Functions
Lambda functions can be passed as arguments to other functions that accept functions or function objects.
Example with std::function:
#include <iostream>
#include <functional>
void Execute(std::function<void()> func) {
func();
}
int main() {
auto message = []() {
std::cout << "Hello from a lambda function" << std::endl;
};
Execute(message);
return 0;
}
Lambdas Capturing this
Lambdas can also capture this to access class members from within the lambda.
#include <iostream>
class MyClass {
private:
int value;
public:
MyClass(int v) : value(v) {}
void printValue() {
auto lambda = [this]() {
std::cout << "Value: " << value << std::endl;
};
lambda();
}
};
int main() {
MyClass obj(42);
obj.printValue(); // Prints 42
return 0;
}
In this example, the lambda captures this to access the member value of the class MyClass.
Generic Lambdas
Since C++14, lambdas can be generic, allowing them to work with different data types.
#include <iostream>
int main() {
auto print = [](auto data) {
std::cout << data << std::endl;
};
print(5); // Prints an integer
print(3.14); // Prints a float
print("Hello"); // Prints a string
return 0;
}
In this example, the lambda print is able to handle different data types thanks to its generic nature.
Practical Examples
Sorting a Collection
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {5, 2, 9, 1, 5, 6};
// Sort using a lambda function
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;
}
Filtering a Collection
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6};
// Filter even numbers
std::vector<int> evens;
std::copy_if(numbers.begin(), numbers.end(), std::back_inserter(evens), [](int num) {
return num % 2 == 0;
});
for (int num : evens) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
Use with std::for_each
The lambda function is very useful with std::for_each to apply an action to each element of a collection.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
// Apply a lambda function to each element
std::for_each(numbers.begin(), numbers.end(), [](int num) {
std::cout << num << " ";
});
std::cout << std::endl;
return 0;
}
