Лямбды и функциональные объекты
Поведение как данные: вызываемые сущности, которые можно передавать, хранить и комбинировать
operator(); а std::function — универсальная коробка, способная хранить любой из них. Вместе они дают возможность передавать логику в алгоритмы, регистрировать обратные вызовы и строить переиспользуемые стратегии.
- читать и писать полный синтаксис лямбды
[captures](params) -> ret { body }, - захватывать переменные по значению, по ссылке и через инициализирующий захват,
- написать функтор и объяснить, как лямбда компилируется в него,
- хранить любую вызываемую сущность в
std::functionи понимать её цену.
1. Что такое лямбда и зачем она нужна?
Представьте лямбду как стикер с инструкцией. Вместо того чтобы писать полноценную именованную функцию где-то в другом месте и ссылаться на неё, вы записываете инструкцию прямо на месте и отдаёте тому, кому она нужна. Читатель (алгоритм, поток, кнопка) сможет выполнить её позже, столько раз, сколько захочет.
До C++11, чтобы задать std::sort собственный порядок сортировки, приходилось писать отдельную именованную функцию или структуру-функтор далеко от места вызова. Это разбрасывало логику и вредило читаемости. Лямбда-выражение позволяет определить функцию прямо в строке:
#include <algorithm>
#include <vector>
std::vector<int> v = {5, 2, 8, 1};
// Сортировка по УБЫВАНИЮ с помощью встроенного компаратора:
std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
// теперь v равно {8, 5, 2, 1}
Часть [](int a, int b) { return a > b; } — это и есть вся функция, записанная там, где она используется. У неё нет собственного имени; компилятор тихо создаёт его за вас.