2016-10-27 3 views
6

Скажем, у меня есть этот код (не обращайте внимания на то, что SecondsToMinutes и MinutesToHours являются копирку друг друга)Действительно ли это использование встроенных функций?

inline float SecondsToMinutes(float seconds) 
{ 
    return seconds/60.0; 
} 
inline float MinutesToHours(float minutes) 
{ 
    return minutes/60.0; 
} 
inline float HoursToDays(float minutes) 
{ 
    return minutes/24.0; 
} 
inline float SeconndsToHours(float seconds) 
{ 
    return MinutesToHours(SecondsToMinutes(seconds)); 
} 
inline float MinutesToDays(float minutes) 
{ 
    return HoursToDays(MinutesToHours(minutes)); 
} 
inline float SeconndsDays(float seconds) 
{ 
    return MinutesToDays(SecondsToMinutes(seconds)); 
} 

Является ли это действительным использование инлайн? Имеет ли это смысл? Это хорошая практика? В конце концов, если я правильно помню, рядный означает, что вызовы функций заменяются функциональными органами, так

return MinutesToDays(SecondsToMinutes(seconds)) 

должен быть эквивалентен

return seconds/60.0/60.0/24.0 

Right?

Или лучше использовать макросы для этого?

#define EXCHANGE_SEC_MIN(x) (x/60.0) 
#define EXCHANGE_MIN_H(x) (x/60.0) 
#define EXCHANGE_H_D(x) (x/24.0) 
#define EXCHANGE_SEC_H(x) (EXCHANGE_MIN_H(EXCHANGE_SEC_MIN(x))) 
#define EXCHANGE_MIN_D(x) (EXCHANGE_H_D(EXCHANGE_MIN_H(x))) 
#define EXCHANGE_SEC_D(x) (EXCHANGE_MIN_D(EXCHANGE_SEC_MIN(x))) 

Какая из них лучше? Или нет? Я бы хотел, чтобы другие центы по этому поводу.

+7

Макросы почти всегда * * неправильный путь :-) – paxdiablo

+2

Кроме того, ваши макросы ошибочны: что произойдет, если вы используете его как 'EXCHANGE_SEC_MIN (a + b)'? – mch

+0

* Макросы почти всегда неправильны * Другими словами, если есть простая альтернатива макросу (которая в этом случае является функцией, независимо от того, встроена или нет), предпочитайте избегать макроса – Leon

ответ

6

Действительно ли это допустимое использование встроенного? Имеет ли это смысл?

Ну, да, но нет.

На данный момент ничего не болит, но он не делает то, что, по вашему мнению, он делает.

В excellent post about inline deft_code правильно говорит:

Говорят, что inline намеки на компилятор, что вы думаете, функция должна быть встраиваемыми. Это могло быть правдой в 1998 году, но в десятилетие компилятору не нужны такие подсказки. Не говоря уже о том, что люди обычно ошибаются, когда речь заходит о оптимизации кода, поэтому большинство компиляторов не учитывают «подсказку».

Таким образом, это не повредит никому, если вы это сделаете, но шанс, что ваш компилятор прослушает ваш намек, практически равен 0. Если он сочтет нужным встроить код, он сделает это сам.

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

Если вы хотите, чтобы убедиться, что ваш код как можно быстрее, и у вас есть доступ к C++ 11 вы должны использовать constexpr:

constexpr float SecondsToMinutes(float seconds) 
{ 
    return seconds/60.0; 
} 
//etc.. 
+0

Обратите внимание, что 'constexpr' - это всего лишь подсказка. Его не нужно оценивать во время компиляции, если оно не используется в постоянном выражении (например, аргумент несимметричного шаблона). Он не может быть оценен во время компиляции, если его аргументы неизвестны во время компиляции, а компиляторы C++ 98 уже могут выполнять постоянную сворачивание по аргументам, которые известны во время компиляции. – Oktalist

+0

@Oktalist Очень правдоподобно, однако в этом случае это скорее будет использоваться компилятором, чем ключевое слово 'inline'. –

7

Действительно ли это действующее использование встроенного? Имеет ли это смысл? Это хорошо практика? В конце концов, если я правильно помню, встроенный означает, что функции звонки заменяются функциональными органами, поэтому

Уверенный, что это. Вы делаете это более разборчивым, что всегда хорошо.

return seconds/60.0/60.0/24.0 

Да, так получилось. Или должен. inline - всего лишь намек, компиляция просто может решить иначе. Но для такого одного лайнера компилятор включит его.

Макросы? Зачем? Если это можно сделать с помощью функций, зачем использовать макросы?

+0

Спасибо за ваш ответ :) Я буду уверен, что буду использовать встроенные функции в будущем, теперь, когда я знаю, для чего они хороши. –

+1

'inline' может оказаться весьма полезным для таких небольших функций, но осторожно, когда это делается при больших функциях. Надувание кода плохое. Внимание! Компилятор будет * НЕ * сокращать ваш код до одного деления из-за математики с плавающей запятой! Если вы не возражаете против нарушения совместимости, включите флаг '-ffast-math'. См. Разницу с и без нее в [godbolt] (https://godbolt.org/g/7NBXMy). – Asu

3

inlineне означает, что функциональные вызовы заменяются функциональными органами. По крайней мере, это не означало, что за последние пятнадцать-то лет: оптимизаторы теперь выходят за рамки заказов от разработчика, и будут выполнять вложение, указали ли вы inline.

inlineна самом деле означает «эта функция может быть определено несколько раз, и линкер должен разобраться и сохранить самое единое определение в конце. Я несу ответственность за то, чтобы все определения идентичны».

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

Обычно, как правило, inline, когда функции определены в заголовке, поскольку этот заголовок в конечном итоге будет включен в несколько единиц перевода, таким образом, определения будут дублированы. Таким образом, если ваш код находится внутри заголовка, это полезно использовать inline.

0

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

Однако inline является лишь подсказкой для компилятора. Стандарты позволяют компилятору игнорировать этот намек, а не встроить функцию. Критерии, по которым компиляторы не выполняют встроенные функции, сильно зависят от компилятора.

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

Смежные вопросы