Шаблонные объектные файлы C ++ - PullRequest
9 голосов
/ 01 июля 2011

Допустим, у меня есть два файла .cpp, file1.cpp и file2.cpp, которые используют std::vector<int>. Предположим, что file1.cpp имеет int main(void). Если я скомпилировал оба файла в file1.o и file2.o, и связал два объектных файла в двоичный файл elf, который я могу выполнить. Я компилирую на 32-битной машине с Ubuntu Linux.

Мой вопрос касается того, как компилятор и компоновщик собирают символы для std :: vector:

  • Когда компоновщик создает мой последний двоичный файл, есть ли дублирование кода? Есть ли у компоновщика один набор «шаблонного» кода для кода в f1.o, который использует std::vector, и другой набор std::vector кода для кода, который содержит f2.o?

Я попробовал это для себя (я использовал g++ -g), и я посмотрел на мою окончательную разборку исполняемого файла, и я обнаружил, что метки, сгенерированные для векторного конструктора и других методов, были, по-видимому, случайными, хотя, похоже, код из f1.o вызвали тот же конструктор, что и код из f2.o. Я не мог быть уверен, однако.

Если компоновщик предотвращает дублирование кода, как он это делает? Должен ли он «знать», что такое шаблоны? Всегда ли это предотвращает дублирование кода при многократном использовании одного и того же шаблонного кода в нескольких объектных файлах?

Ответы [ 3 ]

9 голосов
/ 01 июля 2011

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

Это делается во время компоновки, а не компиляции, потому что каждый файл .o может быть связан с чем-либо, поэтому не может быть лишен чего-то, что впоследствии может понадобиться. Только компоновщик может решить, какой код не используется, какой шаблон повторяется и т. Д. Это делается с помощью « Слабые символы » в списке символов объекта: символы, которые компоновщик может удалить, если они появляются несколько раз ( в отличие от других символов, таких как пользовательские функции, которые нельзя удалить, если они дублируют друг друга и вызывают ошибку компоновки).

4 голосов
/ 01 июля 2011

Ваш вопрос дословно изложен в первом разделе этой документации:

http://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html

0 голосов
/ 01 июля 2011

Технически из-за «одного правила определения» существует только один std::vector<int>, и поэтому код должен быть связан вместе. Может случиться так, что некоторый код встроен, что ускорит время выполнения, но может привести к большему количеству кода.

Если бы у вас был один файл, использующий std::vector<int>, а другой - std::vector<unsigned int>, то у вас было бы 2 класса и потенциально много дублирующегося кода.

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

...