Подтвердить что ты не робот

В С++ что значит для компилятора "встроить" объект функции?

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

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

4b9b3361

Ответ 1

Последний параметр шаблона 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. Это [возможно "dummy" временный] экземпляр класса do_something, который мы создаем, когда вызываем for_each. Но это значение времени выполнения не влияет на цель для вызова (если только operator () не является виртуальным), поэтому он не влияет на inlining.

Ответ 2

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

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

Ответ 3

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

Ответ 4

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

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