Для чего здесь встроенный? - PullRequest
3 голосов
/ 24 ноября 2010

В чем разница между двумя определениями ниже:

#define DEFINE_BIT_MASK_ENUM_AND_OR(Type) \
inline Type EnumBitMaskOr(Type lhs, Type rhs) { return lhs | rhs; } \

#define DEFINE_BIT_MASK_ENUM_AND_OR(Type) \
Type EnumBitMaskOr(Type lhs, Type rhs) { return lhs | rhs; } \

Ответы [ 6 ]

2 голосов
/ 24 ноября 2010

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

inline ключевое слово определяет, приведет ли определение функции (не объявление) к генерации функции в текущем модуле компиляции.В основном это 3 случая:

  • Если вы просто зададите «простое» определение, то должна быть сгенерирована функция и вставлен внешний символ для этой функции.
  • Для определения inline функция может быть сгенерирована , и если это так, то может вставлять или не вставлять внешний символ в объект.
  • Для определения static функция может быть сгенерировано (обычно, если оно используется), но имя никогда не будет внешним символом.

Во-первых, если два модуля компиляции определяют одну и ту же функцию, будет ошибкапри соединении двух объектных файлов в одном исполняемом файле.

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

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


Edit: wrtна комментарий Чарльза.Функции inline также могут быть внешними символами.Правила для этого немного сложны, см. Соответствующий параграф 6.7.4 из C99 ниже.В основном, есть три случая, которые будут работать, если у вас есть несколько единиц перевода, которые будут связаны друг с другом

  1. объявить и определить функцию extern inline в файле .h и объявить этоснова просто inline без extern в одном файле .c.
  2. объявите и определите функцию inline в файле .h и повторно объявите ее без inline в одном файле .c.Фактически это похоже на создание шаблонных функций в C ++.
  3. объявляет и определяет функцию inline в файле .h и повторно объявляет ее extern inline только в одном файле .c.

До версии 4.3 у gcc была другая модель для этого типа реализации inline функций, несовместимая с этой нормативной. См. Также эту страницу для прочтения этой темы.

Любая функция с внутренней связью может быть встроенной функцией.Для функции с внешним связыванием применяются следующие ограничения: Если функция объявлена ​​со встроенным спецификатором функции, то она также должна быть определена в той же единице перевода.Если все объявления области действия файла для функции в модуле перевода включают спецификатор встроенной функции без extern, то определение в этом модуле перевода является встроенным определением.Встроенное определение не предоставляет внешнего определения для функции и не запрещает внешнее определение в другой единице перевода.Встроенное определение предоставляет альтернативу внешнему определению, которое переводчик может использовать для реализации любого вызова функции в том же модуле перевода.Не определено, использует ли вызов функции встроенное определение или внешнее определение.

2 голосов
/ 24 ноября 2010

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

Это может сэкономить время, так как, если выполняемая работа меньше, чем работа по выполнению самого вызова, это чистый выигрыш для его удаления.Это также может замедлить работу, вздув код и уничтожив кеш.

0 голосов
/ 26 ноября 2010

В комментариях к ответ я отметил, что вы хотели знать следующее:

Если функция не может быть встроена и была помечена, поэтому вы получите предупреждение, если выпередать -Winline в GCC.

0 голосов
/ 24 ноября 2010

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

Несколько моментовсделать

  1. Причина, по которой это обычно делается, заключается в том, чтобы сэкономить накладные расходы на вызов другой функции
  2. ключевое слово "inline" - это только запрос к компилятору, и компилятор может решить,соблюдать это или нет
  3. Встраивание может иметь непредвиденные последствия, поэтому его следует использовать с осторожностью
  4. Сегодня компилятор обычно лучше решает, какие функции должны быть встроены для вас, и будет делать это автоматически, еслисоответствующие аргументы предоставляются вашему компилятору
0 голосов
/ 24 ноября 2010

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

0 голосов
/ 24 ноября 2010

Разница в том, что в первом случае не происходит никакого вызова функции. Функция является «встроенной», что означает, что вызов заменяется на тело метода. Это помогает оптимизировать выполнение, так как нет необходимости сохранять контекст перед вызовом и восстанавливать его после.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...