Как работают заголовочные файлы C ++? - PullRequest
8 голосов
/ 16 мая 2010

Когда я включаю некоторую функцию из файла заголовка в программу на C ++, копируется ли весь код файла заголовка в конечный исполняемый файл или генерируется только машинный код для конкретной функции. Например, если я вызываю std::sort из заголовка <algorithm> в C ++, это машинный код, сгенерированный только для функции sort () или для всего файла заголовка <algorithm>.

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

Ответы [ 4 ]

11 голосов
/ 16 мая 2010

Здесь вы смешиваете две разные проблемы:

  1. Заголовочные файлы, обрабатываемые препроцессором
  2. Выборочное связывание кода компоновщиком C ++

Заголовочные файлы

Они просто дословно копируются препроцессором в место, которое include их. Весь код algorithm копируется в файл .cpp, когда вы #include <algorithm>.

Выборочное связывание

Большинство современных компоновщиков не будут ссылаться на функции, которые не вызываются в вашем приложении. То есть написать функцию foo и никогда не вызывать ее - ее код не попадет в исполняемый файл. Так что если вы #include <algorithm> и используете только sort, вот что произойдет:

  • Препроцессор помещает весь файл algorithm в ваш исходный файл
  • Вы звоните только sort
  • Связанный анализирует это и добавляет только источник sort (и вызываемые им функции, если таковые имеются) в исполняемый файл. Код других алгоритмов не добавляется

Тем не менее, шаблоны C ++ еще более усложняют ситуацию. Это сложная проблема, которую нужно объяснить здесь, но в двух словах: шаблоны расширяются компилятором для всех типов, которые вы фактически используете. Поэтому, если vector равно int и vector равно string, компилятор сгенерирует две копии всего кода для класса vector в вашем коде. Поскольку вы используете его (иначе компилятор не сгенерирует его), компоновщик также помещает его в исполняемый файл.

3 голосов
/ 16 мая 2010

Фактически весь файл копируется в файл .cpp, и это зависит от компилятора / компоновщика, если он выбирает только «нужные» функции или все из них.

В общем, упрощенное резюме:

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

Кроме того, это зависит от атрибутов -> объявленная для экспорта функция никогда не будет удалена. С другой стороны, варианты шаблонных функций «генерируются» при использовании, поэтому компилируются только те, которые вы явно используете.

РЕДАКТИРОВАТЬ: код файла заголовка не генерируется, но в большинстве случаев рукописный.

1 голос
/ 16 мая 2010

Если вы #include файл заголовка в исходном коде, он действует так, как если бы текст в этом заголовке был написан вместо директивы препроцессора #include.

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

0 голосов
/ 16 мая 2010

Это зависит от компилятора. Большинство компиляторов сегодня делают анализ потока, чтобы исключить неиспользуемые функции. http://en.wikipedia.org/wiki/Data-flow_analysis

...