В статье Википедии о функциональных объектах это говорит, что такие объекты имеют преимущества производительности при использовании с for_each, потому что компилятор может "встроить" их.
Я являюсь немного туманным на точно, что это означает в этом контексте... или любом контексте, который я смущен для высказывания. Спасибо за любую справку!
Последним параметром шаблона for_each
является functor. Functor - это то, что может быть "вызвано" с помощью оператора ()
(возможно, с аргументами). По определению, существует два отличительных вида functors:
()
(так называемые объекты функции ) также являются functors. Теперь, если бы вы хотели использовать обычную функцию в качестве 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
инстанцируется аргументами
. Обратите внимание, что действительным значением functor в данном случае является указатель функции &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
инстанцируется аргументами
. Вызовы к functor изнутри for_each
будут направлены на do_something::operator()
. Цель вызова известна и фиксируется во время компиляции. Так как целевая функция известна во время компиляции, то вызов может быть легко инкапсулирован.
В последнем случае у нас, конечно, также есть значение времени выполнения, передаваемое в качестве аргумента в for_each
. Это [возможно "фиктивный" временный] экземпляр класса do_something
, который мы создаем при вызове for_each
. Но это значение времени выполнения не влияет на цель вызова (если только оператор ()
не является виртуальным), поэтому не влияет на inlining.
Установка означает только замену каждого вызова этой функции непосредственно телом этой функции.
Это оптимизация для малых функций, так как она уменьшает накладные расходы, связанные с переходом к новой функции, а затем с ее возвращением.
Встроенный процесс, который компилятор может заменить вызов функции содержимым самой функции. Это требует, чтобы компилятор знал содержимое функции при ее компиляции.
Компилятор часто не может этого сделать, если передан указатель на функцию.
Это означает, что определение (код) функции может быть скопировано и избавит вас от вызова функции (что в некоторых системах считается дорогостоящим). Подумайте о замене макросов.