Подтвердить что ты не робот

Могут ли современные встроенные функции компиляторов С++, определенные в файле cpp

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

Поэтому я немного запутался в "автоматических" встроенных возможностях современных компиляторов (а именно gcc 4.43). Когда я определяю функцию внутри cpp, может ли компилятор встраивать его в любом случае, если он считает, что вложение имеет смысл для функции или я лишу его возможности оптимизации? (Что было бы хорошо для большинства функций, но важно знать, что маленькие называются очень часто)

4b9b3361

Ответ 1

Это зависит от ваших флагов компиляции. С -combine и -fwhole-program, gcc будет выполнять функцию, вложенную через границы cpp. Я не уверен, что сделает компоновщик, если вы скомпилируете несколько файлов объектов.

Ответ 2

В блоке компиляции у компилятора не будет проблем с встроенными функциями (даже если они не помечены как встроенные). По сравнению с единицами компиляции это сложнее, но современные компиляторы могут это сделать.

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

Ответ 3

Microsoft Visual С++ смог сделать это, по крайней мере, с Visual Studio 2005. Они называют это "Оптимизация всей программы" или "Генерация кода времени соединения". В этой реализации компилятор фактически не создает машинный код, а записывает предварительно обработанный код С++ в объектные файлы. Затем компоновщик объединит весь код в один огромный блок кода и выполнит фактическую компиляцию.

GCC может сделать это, по крайней мере, с версии 4.5 с существенными улучшениями в GCC 4.7. Насколько мне известно, эта функция по-прежнему считается несколько экспериментальной (по крайней мере, поскольку многие дистрибутивы Linux не используют ее). Реализация GCC работает аналогично, сначала записывая предварительно обработанный источник (в его промежуточном языке GIMPLE) в объектные файлы, а затем компилируя все объектные файлы в один объектный файл, который затем передается в компоновщик (это позволяет GCC продолжать работать с существующими линкерами).

Многие крупные проекты на С++ также делают то, что сейчас называется "сборками единства". Вместо того, чтобы передавать сотни отдельных исходных файлов С++ в компилятор, создается один исходный файл, который включает в себя все другие исходные файлы в проекте. Первоначальный замысел заключается в уменьшении времени компиляции (поскольку заголовки и т.д. Не нужно анализировать снова и снова), но в качестве побочного эффекта он будет иметь тот же результат, что и упомянутые выше методы LTO/LTCG: предоставление компилятор отлично просматривает все функции во всех модулях компиляции.


Я прыгаю между впечатлением от моей изобретательности С++ (MSVC 2010) и ее глупости. Некоторый код, который преобразовал формат пикселей через шаблоны, которые были бы разрешены в 5-10 инструкций по сборке, когда они были правильно встроены, раздувается в килобайтах (!) Вызовов вложенных функций. В других случаях он настолько агрессивно, что целые классы исчезают, хотя они содержат нетривиальные функции.

Ответ 4

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