Могут ли современные компиляторы C ++ встроить функции, определенные в файле cpp - PullRequest
20 голосов
/ 09 декабря 2011

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

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

Ответы [ 4 ]

19 голосов
/ 09 декабря 2011

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

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

17 голосов
/ 07 июля 2012

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

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

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


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

11 голосов
/ 09 декабря 2011

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

6 голосов
/ 09 декабря 2011

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

...