Гарантируется ли наличие только одной копии не встроенной встроенной функции?

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

Или, перефразируя это так, что это почти наверняка вызовет сильное скрежетание зубами: в случаях, когда время предварительной обработки не является проблемой, определение большого метода, встроенного в заголовочный файл, является эффективным способом возможности повторного использования этого кода без необходимости скомпилировать / ссылку в отдельном модуле перевода?

1

Решение

Вы должны быть очень конкретны здесь, так как вы просите гарантии. Стандарт C ++ дает гарантии о поведении программы, а не о реализации, и даже тогда не написан для защиты от вредоносных компиляторов. Многие детали реализации эффективно ограничены поведением. Но не полностью.

Компиляторы могут свободно встраивать в ваш исполняемый файл 2 ^ 17 различных копий любой функции, встроенной или нет. Это было бы бессмысленно, но стандарт не запрещает это! Значение и адрес статических переменных должны были бы быть общими, поскольку это можно наблюдать, и все указатели функций на каждую функцию должны были бы сравниваться равными, если бы код C ++ мог получить их (они могли бы иметь отличное двоичное представление адреса, просто изменить то, что значит сделать ==!).

Это происходит? Нет, но вы попросили гарантию. Стандарт C ++ оставляет огромную свободу для разработчиков. Качество реализации означает, что современные компиляторы не часто делают глупости.

На практике одна встроенная функция создается в каждом .o файл, который использует его. Он отмечен как особый («слабый»). При статическом связывании все эти копии, кроме одной, отбрасываются. Какой из них хранится, зависит от порядка компоновки и может варьироваться от сборки к сборке (особенно частичной сборки). Только одна копия статических локальных объектов хранится в виде симуляции. Все указатели на функцию или статические локальные объекты внутри должен сравнить равными во время выполнения.

Динамическое связывание приводит к тому, что некоторые компиляторы отбрасывают его при сборке в dll. Другие компиляторы, когда .so посмотрите, был ли символ уже загружен, и если это так, не загружайте копию в .so, Динамическое связывание — это тот случай, когда наиболее вероятно, что несколько копий функции будут продолжать существовать и быть доступными. Если этот случай не происходит, вам ясно, и если это так, проверьте это. Стандарт C ++ не описывает динамическое связывание.

3

Другие решения

Если я объявляю большую встроенную функцию, и компилятор в любом случае решает скомпилировать ее как отдельную функцию, гарантированно будет только одна копия этой не встроенной встроенной функции в программе,

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

или может компилятор в конечном итоге создаст несколько не встроенных копий этой функции в разных единицах перевода?

Это может. Они могут даже не быть идентичными: если он может видеть, что аргумент всегда равен нулю в одной единице перевода, он может опустить код для if (arg != nullptr) … `.

3

Я бы порекомендовал вам пройти ниже вопрос:
"в соответствии" ключевое слово против "встраивание" концепция

Для оптимизации, если inline функция:

  • большой хватит, тогда компилятор может нет сделать «встраивание»
  • короткая хватит, тогда компилятор может быть сделать «встраивание»

Однако в обоих случаях Одно правило определения (ODR) гарантировано, так как вы использовали inline ключевое слово.

0
По вопросам рекламы [email protected]