Ваш вопрос - один из вопросов, на который нет ответа, который можно назвать «абсолютной истиной». Затраты на нормальный вызов функции зависят от трех факторов:
Процессор. Затраты на процессоры x86, PPC и ARM сильно различаются, и даже если вы используете только одну архитектуру, накладные расходы также немного различаются между Intel Pentium 4, Intel Core 2 Duo и Intel Core i7. Издержки могут даже заметно различаться между процессорами Intel и AMD, даже если оба работают на одной тактовой частоте, поскольку такие факторы, как размеры кэша, алгоритмы кэширования, шаблоны доступа к памяти и фактическая аппаратная реализация самого кода операции вызова, могут иметь огромные влияние на накладные расходы.
ABI (двоичный интерфейс приложения). Даже с одним и тем же процессором часто существуют различные ABI, которые определяют, как вызовы функций передают параметры (через регистры, через стек или через комбинацию обоих) и где и как происходит инициализация и очистка стекового фрейма. Все это влияет на накладные расходы. Различные операционные системы могут использовать разные ABI для одного и того же процессора; например Linux, Windows и Solaris могут все три использовать разные ABI для одного и того же процессора.
Компилятор. Строгое следование ABI важно только в том случае, если функции вызываются между независимыми единицами кода, например если приложение вызывает функцию из системной библиотеки или пользовательская библиотека вызывает функцию из другой пользовательской библиотеки. Пока функции являются «частными», невидимыми вне определенной библиотеки или двоичного файла, компилятор может «обманывать». Он может не строго следовать ABI, но вместо этого использовать ярлыки, которые приводят к более быстрым вызовам функций. Например. он может передавать параметры в регистр вместо использования стека или может полностью пропустить установку и очистку кадра стека, если в этом нет особой необходимости.
Если вы хотите узнать накладные расходы для конкретной комбинации трех вышеупомянутых факторов, например, для Intel Core i5 в Linux с использованием GCC, единственный способ получить эту информацию - это сравнить разницу между двумя реализациями, одна из которых использует вызовы функций, а другая - где вы копируете код непосредственно в вызывающую программу; таким образом вы наверняка принудительно встраиваете, так как встроенное выражение является лишь подсказкой и не всегда приводит к встраиванию.
Однако настоящий вопрос здесь таков: действительно ли точные накладные расходы имеют значение? Одно можно сказать наверняка: вызов функции всегда имеет накладные расходы. Он может быть маленьким, он может быть большим, но он наверняка существует. И независимо от того, насколько она мала, если функция вызывается достаточно часто в критическом разделе производительности, накладные расходы будут иметь значение в некоторой степени. Встраивание редко делает ваш код медленным, если вы не переборщите с этим; хотя это сделает код больше. Сегодняшние компиляторы довольно хорошо решают, когда включать, а когда нет, так что вам вряд ли когда-нибудь придется ломать голову над этим.
Лично я полностью игнорирую встраивание во время разработки, пока у меня не появится более или менее полезный продукт, который я могу профилировать, и только если профилирование говорит мне, что определенная функция вызывается действительно часто, а также в критически важной для приложения части приложения, тогда я рассмотрю «принудительное включение» этой функции.
Пока мой ответ очень общий, он относится к C так же, как к C ++ и Objective-C. В качестве заключительного слова позвольте мне сказать кое-что о C ++, в частности: виртуальные методы - это двойные косвенные вызовы функций, это означает, что они имеют более высокие издержки вызова функций, чем обычные вызовы функций, и также они не могут быть встроенными. Невиртуальные методы могут быть встроены компилятором или нет, но даже если они не встроены, они все равно значительно быстрее виртуальных, поэтому не следует делать методы виртуальными, если вы действительно не планируете их переопределять или переопределять.