Есть два отдельных решения, которые компилятор принимает в отношении встраивания функций:
- является ли конкретный вызов функции встроенным;
- существует ли не встроенная версия функции.
Первое определяется компилятором в каждом конкретном случае, если в этот момент возможно встраивание. Это не будет возможно, если функция является виртуальной или вызывается через указатель функции, и она не может определить во время компиляции, какая функция должна быть вызвана. Это будет невозможно, если определение не доступно компилятору, возможно, потому что оно определено в другом модуле перевода, и компилятор не выполняет «оптимизацию всей программы». Решение может или не может зависеть от того, объявлена ли функция inline
и других факторов, таких как ее размер и как часто она вызывается.
Второе зависит от того, требуется ли не встроенная версия. Это будет необходимо, если какой-либо вызов к нему не является встроенным. Это также (согласно вашей цитате) потребуется, если что-либо нуждается в адресе функции, так как тогда у него должен быть адрес. Это может происходить либо напрямую (например, путем присвоения адреса указателю функции), либо косвенно (например, виртуальным функциям потребуется, чтобы их адрес где-то сохранялся для поиска во время выполнения в соответствии с динамическим типом объекта).
Наличие не встроенной версии не помешает конкретному вызову функции быть встроенным, хотя возможно, что это может повлиять на решение компилятора, особенно если он настроен на оптимизацию под размер кода.
Подводя итог, ваша цитата является упрощенной и не совсем точной; компилятор все еще может «выполнить вставку», если адрес взят, он просто не может опустить не встроенную версию.