Встроенная функция связи - PullRequest
19 голосов
/ 16 ноября 2010

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

void whateverFunction(parameters)

Компоновщик указывает, что существует множество определений любой функции. Теперь, если изменить его на:

inline void whateverFunction(parameters)

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

Как компоновщик обрабатывает встроенные функции в C ++?

Ответы [ 3 ]

25 голосов
/ 16 ноября 2010

Если функция в заголовке не является встроенной, то несколько определений этой функции (например, в нескольких единицах перевода) являются нарушением правил ODR.

Встроенные функции по умолчанию имеют внешнюю связь. Следовательно, как следствие правил ODR (приведенных ниже), такие множественные определения (например, в нескольких единицах перевода) приемлемы:

$ 3,2 / 5- "может быть более одного определение типа класса (раздел 9), тип перечисления (7.2), встроенный функция с внешней связью (7.1.2), шаблон класса (пункт 14), шаблон нестатической функции (14.5.6), статический член данных шаблона класса (14.5.1.3), функция-член класса шаблон (14.5.1.1) или шаблон специализация для которой какой-то шаблон параметры не указаны (14.7, 14.5.5) в программе при условии, что каждое определение появляется в другом переводчик и предоставил определения удовлетворяют следующему требования. Учитывая такую ​​сущность по имени D определено более чем в одном единица перевода, тогда

- каждое определение D состоит из с одинаковой последовательностью токенов; и [...]

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

Обратите внимание, что если объявление функции в заголовке изменяется на «static inline ....», то встроенная функция явно имеет внутреннюю связь, и каждая единица перевода имеет свою собственную копию статической встроенной функции.

9 голосов
/ 16 ноября 2010

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

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

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

Встроенный просто маскирует проблему.Наличие нескольких определений указывает на проблему где-то.

Juste, будьте осторожны с тем, как вы используете свои заголовки.Не забудьте: - << <code>#ifndef HEADER_NAME / #define HEADER_NAME / #endif >>, чтобы избежать многократного включения.- Не используйте косвенное включение: если вы используете тип в файле, добавьте соответствующий заголовок, даже если другой заголовок в том же файле включает его.

...