Why use anonymous functions in C++? Anonymous functions, known as lambda expressions, help write concise, readable code. They are defined inline without needing a separate function declaration. They're especially useful for short snippets as arguments to algorithms or event handlers.
By the end of this lesson, you'll understand what anonymous functions (lambda expressions
) are, how to create them, and how they can simplify your code.
Anonymous functions in C++ are functions defined without a name, commonly called lambda expressions. The basic syntax of a lambda expression is:
C++1[capture](parameters) { body };
- Capture: Specifies which outside variables are accessible in the lambda.
- Parameters: Function parameters.
- Body: The actual code to execute.
Consider the following code snippet where we use a lambda function to print elements of a vector
. We will put the lambda function into a variable and use it later.
C++1#include <iostream> 2#include <vector> 3 4int main() { 5 std::vector<int> numbers = {1, 2, 3, 4, 5}; 6 7 // Lambda to print numbers 8 auto print_number = [](int n) { 9 std::cout << n << ' '; 10 }; 11 12 for (int n : numbers) { 13 print_number(n); 14 } 15 // Output: 1 2 3 4 5 16 17 return 0; 18}
Here, print_number
is a variable that stores the lambda function that takes an integer n
and prints it. This lambda is used in a for
loop to print each number in the numbers
vector.
Sometimes, we must access variables from the surrounding scope within your lambda. This is done using the capture clause:
C++1#include <iostream> 2#include <vector> 3 4int main() { 5 std::vector<int> numbers = {1, 2, 3, 4, 5}; 6 int factor = 2; 7 8 // Lambda capturing the 'factor' variable 9 auto multiply_by_factor = [factor](int &n) { 10 n *= factor; 11 }; 12 13 for (int &n : numbers) { 14 multiply_by_factor(n); 15 } 16 17 for (int n : numbers) { 18 std::cout << n << ' '; 19 } 20 std::cout << '\n'; // Output: 2 4 6 8 10 21 22 return 0; 23}
Here, multiply_by_factor
is a lambda capturing the factor
variable by value. It multiplies each element of the numbers
vector by factor
.
By default, lambdas capture variables by value, and the captured variables are treated as const
. However, you can modify captured variables by using the mutable
keyword.
C++1#include <iostream> 2 3int main() { 4 int x = 10; 5 6 auto increment = [x]() mutable { 7 x++; 8 std::cout << x << '\n'; // Output: 11 9 }; 10 11 increment(); 12 std::cout << x << '\n'; // Output: 10 13 14 return 0; 15}
In this example, mutable
allows the lambda to modify the captured variable x
. The original x
remains unchanged outside the lambda.
Lambda functions are particularly useful when passing custom behavior to algorithms like std::sort
. When studying the STL library, we will explore this behavior in detail in one of the following courses.
But let's look at one basic example now. The std::sort
function takes another function defining the rules of sorting as an argument. Here, we use a lambda function to sort a vector of integers in descending order.
C++1#include <iostream> 2#include <vector> 3#include <algorithm> // for std::sort 4 5int main() { 6 std::vector<int> numbers = {1, 5, 3, 4, 2}; 7 8 // Lambda for custom sorting in descending order 9 std::sort(numbers.begin(), numbers.end(), [](int a, int b) { 10 return b < a; 11 }); 12 13 for (int n : numbers) { 14 std::cout << n << ' '; 15 } 16 std::cout << '\n'; // Output: 5 4 3 2 1 17 18 return 0; 19}
In this example, we passed a lambda function to the std::sort
algorithm. The lambda function takes two parameters a
and b
and returns true
if b
is less than a
, effectively sorting the vector in descending order.
We learned about anonymous functions (lambda expressions
) in C++. We started with a simple example, explored capturing variables, and discussed advanced topics like mutable lambdas and passing lambdas as arguments.
Lambda expressions enable us to write more concise, readable, and maintainable code.
Now it's time to put your knowledge into practice. You'll work with anonymous functions in different scenarios, implement them, and understand their advantages. Practicing will reinforce the concepts learned and provide hands-on experience with lambda expressions.