Последний параметр шаблона for_each
- это функтор . Functor - это то, что может быть вызвано с помощью оператора ()
(возможно, с аргументами). По определению, есть два отличительных типа функторов:
- Обычные функции, не являющиеся членами
функторы.
- Объекты типа класса с перегруженным оператором
()
(так называемые функциональные объекты ) также являются функторами.
Теперь, если вы хотите использовать обычную функцию в качестве функтора для for_each
, она будет выглядеть примерно так:
inline void do_something(int &i) { /* do something */ }
int main() {
int array[10];
std::for_each(array, array + 10, &do_something);
}
В этом случае шаблон for_each
создается с [выведенными] аргументами <int *, void (*)(int &)>
. Обратите внимание, что фактическим значением функтора в этом случае является указатель на функцию &do_something
, передаваемый в качестве аргумента функции. С точки зрения функции for_each
это значение времени выполнения. А поскольку это значение времени выполнения, вызовы функтора не могут быть встроенными. (Так же, как в общем случае невозможно встроить любой вызов, сделанный через указатель на функцию).
Но если вместо этого мы используем функциональный объект, код может выглядеть следующим образом
struct do_something {
void operator()(int &i) { /* do something */ }
};
int main() {
int array[10];
std::for_each(array, array + 10, do_something());
}
В этом случае шаблон for_each
создается с [выведенными] аргументами <int *, do_something>
. Звонки на функтор изнутри for_each
будут направлены на do_something::operator()
. Цель для вызова известна и исправлена во время компиляции. Поскольку целевая функция известна во время компиляции, вызов может быть легко встроен.
В последнем случае у нас, конечно, также есть значение времени выполнения, переданное в качестве аргумента for_each
. Это [возможно, «фиктивный» временный] экземпляр класса do_something
, который мы создаем при вызове for_each
. Но это значение времени выполнения не влияет на цель для вызова (если operator ()
не является виртуальным), поэтому оно не влияет на встраивание.