Лямбды
Общие сведения о лямбда-функциях
Лямбда-функции определяются с помощью синтаксиса []() {}
. Они могут принимать параметры, возвращать значения и захватывать переменные из окружающего контекста.
В этом примере лямбда-функция add
складывает два числа.
Захват переменных
Лямбда-функции могут захватывать переменные из окружающего контекста различными способами:
- По значению
[=]
- По ссылке
[&]
- Конкретные переменные по значению
[a, b]
- Конкретные переменные по ссылке
[&a, &b]
Здесь лямбда-функция захватывает переменные x
и y
по значению.
Использование лямбда-функций
Лямбда-функции часто используются для краткосрочных операций, таких как сортировка, фильтрация или обход контейнеров.
В данном примере лямбда-функция используется для сортировки вектора.
Лямбда-функции и шаблоны
Лямбда-функции могут быть обобщенными, если они не захватывают переменные из окружающего контекста. Это делает их удобными для использования в шаблонных функциях и алгоритмах.
Здесь шаблонная функция apply
принимает лямбда-функцию в качестве аргумента.
Хранение лямбда-функций
Внутреннее устройство лямбда-функций
Каждая лямбда-функция в C++ является объектом, который включает в себя:
- Тело функции.
- Захваченные переменные (если есть).
Когда лямбда-функция объявляется, компилятор генерирует анонимный класс, который содержит:
operator()
, представляющий тело лямбда-функции.- Члены данных для хранения захваченных переменных.
Рассмотрим пример:
В этом примере компилятор создает анонимный класс с членами a
и &b
, а также методом operator()(int x)
.
std::function и лямбда-функции
Для хранения лямбда-функций, особенно тех, которые захватывают переменные, часто используется std::function
. Это шаблонный класс, который может хранить любые вызываемые объекты (включая функции, лямбда-функции, функторы и т. д.).
В данном примере std::function<int(int)>
используется для хранения лямбда-функции, которая захватывает переменную x
.
Преимущества и недостатки использования std::function
Преимущества
- Гибкость:
std::function
может хранить любые вызываемые объекты, включая лямбда-функции с захватом. - Безопасность типов:
std::function
обеспечивает строгую проверку типов, что уменьшает вероятность ошибок.
Недостатки
- Накладные расходы: Использование
std::function
может добавить некоторые накладные расходы на производительность и память из-за динамического выделения памяти и механизма виртуальных функций. - Необходимость шаблонного параметра: Требуется явное указание сигнатуры функции, что может быть не всегда удобно.
Пример хранения лямбда-функции без std::function
Иногда лямбда-функцию можно сохранить напрямую в переменную автоматического типа, если она не захватывает переменные:
Резюме
Лямбда-функции в C++ — это объекты, которые могут захватывать и хранить переменные из окружающего контекста. Они хранятся как экземпляры анонимных классов, сгенерированных компилятором. Для хранения и передачи лямбда-функций, особенно тех, которые захватывают переменные, часто используется std::function
. Это обеспечивает гибкость и безопасность, но может добавить некоторые накладные расходы на производительность и память.