Компилятор решает, когда встроить мои функции (в C ++)? - PullRequest
9 голосов
/ 30 июля 2009

Я понимаю, что вы можете использовать ключевое слово inline или просто поместить метод в объявление класса ala short ctor или метод getter, но компилятор принимает окончательное решение о том, когда включать мои методы?

Например:

inline void Foo::vLongBar()
{
   //several function calls and lines of code
}

Будет ли компилятор игнорировать мое встроенное объявление, если считает, что это сделает мой код неэффективным?

В качестве дополнительной проблемы, если у меня есть метод get, объявленный вне моего класса, например:

void Foo::bar() { std::cout << "baz"; }

Будет ли компилятор встроен в это под одеялом?

Ответы [ 9 ]

15 голосов
/ 30 июля 2009

Да, окончательное решение о том, включать ли ваш код в код или нет, находится в компиляторе C ++. Встроенное ключевое слово является предложением, а не требованием.

Вот некоторые подробности о том, как это решение обрабатывается в компиляторе Microsoft C ++

10 голосов
/ 30 июля 2009

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

Основная причина того, что функция не встроена, заключается в том, что она значительно увеличит общий размер кода, предотвращая удержание iot в кэше процессора. На самом деле это будет скорее пессимизация, чем оптимизация.

Что касается того, чтобы позволить программисту решить выстрелить себе в ногу или в другое место, вы можете встроить функцию самостоятельно - напишите код, который был бы в функции на том месте, где был бы сайт вызова функции.

4 голосов
/ 30 июля 2009

Как уже отмечали другие, ключевое слово inline является всего лишь предложением компилятору встроить код. Поскольку компилятор будет обычно встроенный код, который не был помечен inline, а не встроенный код, который имеет, ключевое слово кажется таким же избыточным, как register или (до C ++ 0x) auto.

Однако есть еще одна вещь, которая влияет на ключевое слово inline: она изменяет связь функции с external (по умолчанию для функций) на inline . Встроенное связывание позволяет каждому модулю компиляции содержать собственную копию объектного кода, а компоновщик удаляет избыточные копии из конечного исполняемого файла. Если это напоминает вам шаблоны, да, шаблоны также используют встроенную связь.

4 голосов
/ 30 июля 2009

Как уже писали многие, окончательное решение всегда остается за компилятором, даже если вы можете дать твердые подсказки, такие как forceinline.
Часть обоснования заключается в том, что встраивание не является автоматическим переключателем «идти быстрее». Слишком большое встраивание может сделать ваш код намного больше и может помешать другим оптимизациям. См. FAQ по C ++ Lite о встроенных функциях и производительности .

3 голосов
/ 30 июля 2009

Просто добавь мои 5 центов ...

Я нашел эту Гуру недели статью о встраивании очень полезной.

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

С уважением,
* Ованес * 1010

3 голосов
/ 30 июля 2009

Да, компилятор принимает окончательное решение. В VS вы можете даже встроить рекурсивные функции на указанную глубину ;)

#pragma inline_depth( [0... 255] )
2 голосов
/ 30 июля 2009

В качестве дополнительной проблемы, если у меня есть метод get, объявленный вне моего класса, как этот:

void Foo::bar() { std::cout << "baz"; }

Будет ли компилятор встроен в это под одеялом?

Это зависит. Это может для всех вызывающих абонентов в одной и той же единице перевода (файл .cpp и все его определения #included). Но он все еще должен скомпилировать не встроенную версию, потому что могут быть вызывающие функции этой функции за пределами модуля перевода. Вы можете увидеть это на работе (если ваш компилятор действительно может это сделать) на высоких уровнях оптимизации. (В частности: сравните то, что происходит, когда вы #include все ваши файлы .cpp в одном .cpp с типичным макетом. Со всеми определениями в одном модуле перевода возможности для такого встраивания резко возрастают.)

1 голос
/ 30 июля 2009

Если вам действительно, безусловно, обязательно, НЕОБХОДИМО встраивать код, всегда есть макрос. C поддерживает их в течение многих лет, и, поскольку они являются просто заменой текста перед компиляцией, они действительно, действительно, встраивают все, что вы пишете.

Именно поэтому ключевое слово 'inline' (и даже в некоторых случаях принудительные варианты) может позволить себе не иметь стандартного способа его принудительного применения - вы всегда можете просто написать макрос.

При этом ключевое слово inline часто лучше, потому что компилятор довольно часто знает, имеет ли смысл делать встроенную функцию или нет, и потому что inline может взаимодействовать с остальными оптимизациями компилятора.

1 голос
/ 30 июля 2009

Насколько мне известно, компилятор автоматически сделает функцию, которую вы объявили встроенной (или написанной в объявлении класса), не-встроенную, если он найдет цикл, например for, while и т. Д. Это один из примеров, когда компилятор имеет последнее слово во встроенных функциях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...