По меньшей мере четыре веские причины:
Разделение проблем
В вашем конкретном примере основанный на функторе подход имеет то преимущество, что отделяет логику итерации от логики вычисления среднего значения , Таким образом, вы можете использовать свой функтор в других ситуациях (подумайте обо всех других алгоритмах в STL), и вы можете использовать другие функторы с for_each
.
Параметризация
Вы можете параметризовать функтор легче. Например, у вас может быть функтор CalculateAverageOfPowers
, который принимает среднее значение квадратов, кубов и т. Д. Ваших данных, которое было бы записано так:
class CalculateAverageOfPowers
{
public:
CalculateAverageOfPowers(float p) : acc(0), n(0), p(p) {}
void operator() (float x) { acc += pow(x, p); n++; }
float getAverage() const { return acc / n; }
private:
float acc;
int n;
float p;
};
Конечно, вы могли бы сделать то же самое с традиционной функцией, но затем затрудняет использование с указателями функций, потому что у него есть другой прототип CalculateAverage
.
Состоятельность
И поскольку функторы могут быть stateful, вы можете сделать что-то вроде этого:
CalculateAverage avg;
avg = std::for_each(dataA.begin(), dataA.end(), avg);
avg = std::for_each(dataB.begin(), dataB.end(), avg);
avg = std::for_each(dataC.begin(), dataC.end(), avg);
, чтобы усреднить по множеству различных наборов данных.
Обратите внимание, что почти все алгоритмы STL / контейнеры, которые принимают функторы, требуют от них быть «чистыми» предикатами, т. е. не имеют наблюдаемого изменения состояния во времени. for_each
является особым случаем в этом отношении (см., например, Эффективная стандартная библиотека C ++ - for_each vs. transform ).
Производительность
Функторы часто могут быть встроенный компилятором (STL - это куча шаблонов, в конце концов). В то время как теоретически это верно для функций, компиляторы обычно не будут встроены в указатель функций. Канонический пример - сравнение std::sort
vs qsort
;
Сводка
Конечно, можно эмулировать первые три с традиционными функциями и указателями, но при этом, как правило, 5-10 раз быстрее, если предположить, что сам предикат сравнения прост. он становится намного проще с функторами.
Это известная ошибка, которая присутствовала в Kotlin версии 1.3.0.
см. https://youtrack.jetbrains.com/issue/KT-28061
Если возможно, обновить до версии Kotlin> = 1.3.20