Lesson 3
Anonymous Functions in C++
Lesson Introduction

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.

Introduction to Anonymous Functions

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.
Simple Example of Anonymous Functions

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.

Capturing Variables in Lambda

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.

Mutable Lambdas

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.

Using Lambda Functions with `std::sort`

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.

Lesson Summary

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.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.