#c #class #methods #linker
#c #класс #методы #компоновщик
Вопрос:
Ради любопытства, если вы помещаете определение метода внутри определения класса в заголовке, а компилятор не вставляет его, то в какой объектный файл или файлы этот метод помещается для доступа на этапе компоновки? Помещается ли это в каждый obj-файл, который включает заголовок, а затем дополнительные копии выбрасываются на этапе компоновки?
Комментарии:
1. Вы всегда можете попробовать такие утилиты, как «objdump» и «nm», чтобы знать это. 🙂
2. Определения функций-членов внутри определения класса являются встроенными по определению (в частности, 9.3 / 2 Стандарта), точно так же, как если бы они были объявлены
inline
.
Ответ №1:
Помещается ли это в каждый obj-файл, который включает заголовок, а затем дополнительные копии выбрасываются на этапе компоновки?
В общем, да. Смотрите этот документ.
Ответ №2:
Это зависит от компилятора, но GCC, по крайней мере, попытается поместить его в тот же объектный файл, что и первый нестроевой элемент. Если все элементы являются встроенными, то в каждом объектном файле, для которого требуется функция, будет копия (не обязательно все файлы, которые включают определение класса), а дополнительные копии выбрасываются при связывании.
Ответ №3:
Если компилятор отклоняет встраивание некоторой функции-члена, которая определена в строке в теле класса или определяется как inline
функция вне тела класса, компилятор вставит скомпилированную версию функции в каждый obj-файл, который использует эту функцию. Обратите внимание, что это отличается от вставки скомпилированной версии каждой функции, объявленной в заголовке. Рассматриваемый файл должен вызывать эту (предположительно) встроенную функцию.
И да, компоновщик удалит дублирующиеся записи. Символы, сгенерированные в таблице символов для этих встроенных функций, имеют слабую связь. Сравните с функциями, которые не встроены: они имеют обычную связь, и если одна из них реплицируется, у вас неопределенное поведение. Типичный ответ компоновщика — пожаловаться, а затем умереть.