Почему я должен делать что-то вроде этого:
inline double square (double x) { return x*x;}
вместо
double square (double x) { return x*x;}
Есть ли разница?
Почему я должен делать что-то вроде этого:
inline double square (double x) { return x*x;}
вместо
double square (double x) { return x*x;}
Есть ли разница?
Первый (используя inline
) позволяет поместить эту функцию в файл заголовка, где он может быть включен в несколько исходных файлов. Использование inline
делает идентификатор в области файлов, подобно объявлению его static
. Без использования inline
вы получите ошибку компоновщика с несколькими символами.
Конечно, это в дополнение к подсказке компилятору о том, что функция должна быть скомпилирована inline в том месте, где она используется (избегая служебных функций вызова функции). Компилятор не обязан воздействовать на подсказку inline
.
Да, есть разница. https://isocpp.org/wiki/faq/inline-functions.
Когда вы указываете, что функция является встроенной, вы вынуждаете компилятор помещать код метода туда, где он вызывается.
void myfunc() {
square(2);
}
совпадает с
void myfunc() {
2 * 2;
}
Вызов функции хорош для ясности кода, но когда эта функция называется локальным состоянием, она должна быть перенесена в стек, для этого метода настраивается новое локальное состояние, и когда это делается, предыдущее состояние должно быть совал. Это накладные расходы.
Теперь, если вы повышаете уровень оптимизации, компилятор будет принимать решения, такие как разворачивание циклов или функции инкрустации. Компилятор по-прежнему может игнорировать встроенный оператор.
В современном компиляторе, вероятно, не так много. Он может быть встроен без inline
и не может быть встроен в inline
.
Из Википедии: встроенная функция - это функция, с которой компилятор запросил выполнить встроенное расширение. Другими словами, программист запросил, чтобы компилятор вставлял весь кусок функции в каждое место, вызываемое функцией, а не генерировал код для вызова функции в одном месте, где он определен. Компиляторы не обязаны соблюдать этот запрос.
Встроенная функция, если компилятор отвечает, будет включать встроенную функцию в код, в котором он был вызван, как если бы не вызывалась функция (как если бы вы поместили логику в вызывающую функцию) и избегаете служебных вызовов функции.
inline
хорошо работает с концепцией процедурной абстракции:
inline double square (double x) { return x*x;}
int squareTwice(double x) {
double first = square(x);
double second = square(x);
return first * second;
}
Вышеупомянутое в корне похоже на следующее:
int squareTwice(double x) {
double first = x*x;
double second = x*x;
return first * second;
}
Это происходит потому, что когда компилятор inline-расширяет вызов функции, код функции вставляется в поток кода вызывающего абонента; следовательно, может быть проще описать второй пример в первом примере.
Процедурная абстракция позволяет разбить подпрограмму на более мелкие подпрограммы, которые намного легче читать (хотя это может быть выбор стиля).