Что такое функторы в C++ и зачем они нужны?
Что такое функтор?
Функтор (или функциональный объект) — это класс или структура, в которой перегружен оператор вызова функции operator(). Благодаря этому объект такого класса можно использовать так же, как обычную функцию:
class Adder {
public:
int operator()(int a, int b) const {
return a + b;
}
};
Adder add; // создаем объект-функтор
int result = add(3, 4); // вызываем как функцию → result = 7
Почему функторы лучше обычных функций?
- Сохранение состояния. Функтор может хранить данные между вызовами. Обычная функция для этого использует глобальные или статические переменные — это небезопасно и неудобно.
- Производительность. Компилятор может легко встроить (inline) вызов функтора, так как тип объекта известен во время компиляции. С указателем на функцию это сложнее.
- Гибкость. Функтор может иметь несколько перегруженных версий
operator().
Пример с состоянием
Допустим, нужно подсчитать, сколько раз компаратор вызывался при сортировке:
#include <iostream>
#include <vector>
#include <algorithm>
struct CountingComparator {
int count = 0;
bool operator()(int a, int b) {
++count;
return a < b;
}
};
int main() {
std::vector<int> v = {3, 1, 4, 1, 5};
CountingComparator comp;
std::sort(v.begin(), v.end(), comp);
std::cout << "Comparisons: " << comp.count << std::endl; // выведет количество
return 0;
}
Функторы и лямбды
Лямбда-выражения — это синтаксический сахар для создания безымянных функторов. Компилятор превращает лямбду в класс с перегруженным operator(). Например:
auto lambda = [](int a, int b) { return a < b; };
// Компилятор создает что-то вроде:
struct __lambda {
bool operator()(int a, int b) const { return a < b; }
} lambda;
Лямбды удобнее для одноразового использования, но если функтор нужен многократно или с большим количеством внутренних данных, лучше написать класс явно.
Практический пример: фильтрация по порогу
class ThresholdFilter {
int threshold;
public:
ThresholdFilter(int t) : threshold(t) {}
bool operator()(int value) const {
return value > threshold;
}
};
// Использование:
std::vector<int> data = {1, 5, 8, 3, 10};
ThresholdFilter filter(5);
// Удаляем элементы, не проходящие фильтр
data.erase(std::remove_if(data.begin(), data.end(), filter), data.end());
// Останется: 8, 10
Итог
Функторы — мощный инструмент, который сочетает гибкость объектов и синтаксис функций. Они особенно полезны в алгоритмах STL, callback-системах и везде, где нужно сохранять контекст между вызовами. Лямбды — их современная альтернатива, но понимание функторов необходимо для глубокого понимания C++.
<<Дополнение: функторы как стратегии (полиморфизм без виртуальных функций)
Еще одно важное применение функторов — реализация паттерна "Стратегия" с нулевыми накладными расходами. Вместо того чтобы использовать виртуальные функции (что замедляет код), можно параметризовать алгоритм функтором через шаблон:
template <typename Comparator>
void sort_and_print(std::vector<int>& v, Comparator comp) {
std::sort(v.begin(), v.end(), comp);
for (int x : v) std::cout << x << " ";
}
struct Ascending {
bool operator()(int a, int b) const { return a < b; }
};
struct Descending {
bool operator()(int a, int b) const { return a > b; }
};
// Использование:
std::vector<int> vec = {3, 1, 4, 1, 5};
sort_and_print(vec, Ascending{}); // 1 1 3 4 5
sort_and_print(vec, Descending{}); // 5 4 3 1 1
Компилятор создаст две разные версии функции sort_and_print — для каждого типа функтора. Это даёт максимальную производительность, так как вызов operator() будет встроен (inlined). С указателями на функцию или виртуальными методами такого не добиться.
Кроме того, функторы можно комбинировать. Например, создать функтор, который применяет несколько операций последовательно:
class Compose {
std::function<int(int)> f, g;
public:
Compose(std::function<int(int)> f, std::function<int(int)> g) : f(f), g(g) {}
int operator()(int x) const { return f(g(x)); }
};
Это делает функторы отличным инструментом для функционального программирования в C++.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги
Где и как эффективно учить Python: Лучшие курсы и интерактивные платформы для самостоятельного обучения