Если я объявляю большую встроенную функцию, и компилятор в любом случае решает скомпилировать ее как отдельную функцию, гарантированно ли будет только одна копия этой не встроенной встроенной функции в программе, или компилятор может создать несколько копии этой функции в разных единицах перевода?
Или, перефразируя это так, что это почти наверняка вызовет сильное скрежетание зубами: в случаях, когда время предварительной обработки не является проблемой, определение большого метода, встроенного в заголовочный файл, является эффективным способом возможности повторного использования этого кода без необходимости скомпилировать / ссылку в отдельном модуле перевода?
Вы должны быть очень конкретны здесь, так как вы просите гарантии. Стандарт C ++ дает гарантии о поведении программы, а не о реализации, и даже тогда не написан для защиты от вредоносных компиляторов. Многие детали реализации эффективно ограничены поведением. Но не полностью.
Компиляторы могут свободно встраивать в ваш исполняемый файл 2 ^ 17 различных копий любой функции, встроенной или нет. Это было бы бессмысленно, но стандарт не запрещает это! Значение и адрес статических переменных должны были бы быть общими, поскольку это можно наблюдать, и все указатели функций на каждую функцию должны были бы сравниваться равными, если бы код C ++ мог получить их (они могли бы иметь отличное двоичное представление адреса, просто изменить то, что значит сделать ==
!).
Это происходит? Нет, но вы попросили гарантию. Стандарт C ++ оставляет огромную свободу для разработчиков. Качество реализации означает, что современные компиляторы не часто делают глупости.
На практике одна встроенная функция создается в каждом .o
файл, который использует его. Он отмечен как особый («слабый»). При статическом связывании все эти копии, кроме одной, отбрасываются. Какой из них хранится, зависит от порядка компоновки и может варьироваться от сборки к сборке (особенно частичной сборки). Только одна копия статических локальных объектов хранится в виде симуляции. Все указатели на функцию или статические локальные объекты внутри должен сравнить равными во время выполнения.
Динамическое связывание приводит к тому, что некоторые компиляторы отбрасывают его при сборке в dll. Другие компиляторы, когда .so
посмотрите, был ли символ уже загружен, и если это так, не загружайте копию в .so
, Динамическое связывание — это тот случай, когда наиболее вероятно, что несколько копий функции будут продолжать существовать и быть доступными. Если этот случай не происходит, вам ясно, и если это так, проверьте это. Стандарт C ++ не описывает динамическое связывание.
Если я объявляю большую встроенную функцию, и компилятор в любом случае решает скомпилировать ее как отдельную функцию, гарантированно будет только одна копия этой не встроенной встроенной функции в программе,
Нет, такой гарантии нет. Какие является гарантируется, что будет только одна копия статических переменных, объявленных в функции, и что если вы возьмете адрес функции, вы всегда получите одно и то же значение.
или может компилятор в конечном итоге создаст несколько не встроенных копий этой функции в разных единицах перевода?
Это может. Они могут даже не быть идентичными: если он может видеть, что аргумент всегда равен нулю в одной единице перевода, он может опустить код для if (arg != nullptr
) … `.
Я бы порекомендовал вам пройти ниже вопрос:
"в соответствии" ключевое слово против "встраивание" концепция
Для оптимизации, если inline
функция:
Однако в обоих случаях Одно правило определения (ODR) гарантировано, так как вы использовали inline
ключевое слово.