В C++ что означает то, чтобы компилятор “встроил” функциональный объект?

В статье Википедии о функциональных объектах это говорит, что такие объекты имеют преимущества производительности при использовании с for_each, потому что компилятор может "встроить" их.

Я являюсь немного туманным на точно, что это означает в этом контексте... или любом контексте, который я смущен для высказывания. Спасибо за любую справку!

15
задан Monte Hurd 8 February 2010 в 23:21
поделиться

4 ответа

Последним параметром шаблона for_each является functor. Functor - это то, что может быть "вызвано" с помощью оператора () (возможно, с аргументами). По определению, существует два отличительных вида functors:

  1. Обычными функциями, не являющимися членами, являются забавные люди.
  2. Объекты типа класса с перегруженным оператором () (так называемые объекты функции ) также являются 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.

14
ответ дан 1 December 2019 в 02:37
поделиться

Установка означает только замену каждого вызова этой функции непосредственно телом этой функции.

Это оптимизация для малых функций, так как она уменьшает накладные расходы, связанные с переходом к новой функции, а затем с ее возвращением.

3
ответ дан 1 December 2019 в 02:37
поделиться

Встроенный процесс, который компилятор может заменить вызов функции содержимым самой функции. Это требует, чтобы компилятор знал содержимое функции при ее компиляции.

Компилятор часто не может этого сделать, если передан указатель на функцию.

7
ответ дан 1 December 2019 в 02:37
поделиться

Это означает, что определение (код) функции может быть скопировано и избавит вас от вызова функции (что в некоторых системах считается дорогостоящим). Подумайте о замене макросов.

3
ответ дан 1 December 2019 в 02:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: