Подтвердить что ты не робот

Что значит для функции С++ быть встроенным?

См. главу: что означает, что функция С++ является встроенной?

4b9b3361

Ответ 1

Функция помещается в код, а не на вызов, аналогично использованию макросов (концептуально)

Это может улучшить скорость (без вызова функции), но вызывает раздувание кода (если функция используется 100 раз, теперь у вас есть 100 копий)

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

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

Ответ 2

Как и другие (совершенно правильные) ответы о последствиях производительности inline, в С++ вы также должны отметить, что это позволяет безопасно помещать функцию в заголовок:

// my_thing.h
inline int do_my_thing(int a, int b) { return a + b; }

// use_my_thing.cpp
#include "my_thing.h"
...
    set_do_thing(&do_my_thing);

// use_my_thing_again.cpp
...
    set_other_do_thing(&do_my_thing);

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

Без ключевого слова inline большинство компиляторов выдаст ошибку о множественном определении, например, для MSVC:

use_my_thing_again.obj : error LNK2005: "int __cdecl do_my_thing(int,int)" ([email protected]@[email protected]) already defined in use_my_thing.obj
<...>\Scratch.exe : fatal error LNK1169: one or more multiply defined symbols found

Ответ 3

Это означает только одно и только одно: компилятор исключит несколько определений функции.

Функция обычно не может быть определена несколько раз (т.е. если вы поместите определение не встроенной функции в заголовок, а затем # включите ее в несколько единиц компиляции, вы получите ошибку компоновщика). Маркировка определения функции как "inline" подавляет эту ошибку (компоновщик гарантирует, что происходит правильная вещь).

ЭТО НЕ ОЗНАЧАЕТ БОЛЬШЕ!

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

Элидинг нескольких определений - это то, что нужно запомнить.

Ответ 4

@OldMan

Компиляторы только встроенные не помечены как встроенные функции ТОЛЬКО, если вы попросите его сделать это.

Только если по запросу вы имеете в виду "включить оптимизацию".

Правильно это относится только к эффектам к казусе.

Правильно в обоих.

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

Что значит "символы не экспортируются"? встроенные функции не являются статическими. Их имена видны; они имеют внешнюю связь. Чтобы привести цитату из стандарта С++:

void h(); inline void h();//внешняя связь

inline void l(); void l();//внешняя связь

Множество определений вещь очень важна. Обязательно:

Встроенная функция должна быть определена в каждой единицы перевода, в которой она используется, и должна иметь точно то же определение в каждом случае (3.2). [Примечание: вызов встроенной функции может быть встречен до определения появляется в блоке перевода. ] Если функция с внешней связью объявлена ​​встроенной в один перевод единица, она должна быть объявлена ​​встроенной во все единицы перевода, в которых она появляется; диагностика не требуется. встроенная функция с внешней связью должна иметь один и тот же адрес во всех единицах трансляции.

Ответ 5

Тело функции буквально вставлено внутри функции вызывающего абонента. Таким образом, если у вас есть несколько вызовов этой функции, вы получаете несколько копий кода. Преимущество в том, что вы получаете более быстрое выполнение.

Обычно очень короткая функция встроена, когда копия тела функции будет не намного больше обычного кода пролога/эпилога, сгенерированного для обычного вызова функции.

Более подробно вы можете прочитать в статье MSDN о inline - http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx

Ответ 6

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

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

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

Часто задаваемые вопросы по С++ объясняют тонкости ключевого слова: http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.3

Ответ 7

Неформально это означает, что компиляторам разрешено пересаживать содержимое функции на сайт вызова, так что нет вызова функции. Если у вашей функции есть большие управляющие операторы (например, if, switch и т.д.), И условия могут быть оценены во время компиляции на сайте вызова (например, постоянные значения, используемые на сайте вызова), тогда ваш код заканчивается (неиспользуемые ветки выпадают).

Более формально, встроенные функции также имеют разную связь. Я позволю экспертам на С++ обсуждать этот аспект.

Ответ 8

Вызов функции накладывает определенное ограничение производительности для ЦП только при наличии линейного потока инструкций. Регистры CPU должны быть записаны в другое место и т.д. Очевидно, что преимущества наличия функций обычно превышают штраф за производительность. Но, когда производительность будет проблемой, например, легендарной функцией "внутренний цикл" или каким-либо другим узким местом, компилятор может вставить машинный код для функции в основной поток исполнения вместо того, чтобы пропустить налог с ЦП для вызова функции.

Ответ 9

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

Когда компилятор решает, что функция должна быть встроена, вызов функции в коде вызывающего абонента заменяется кодом calee. Это означает, что вы сохраняете операции стека, сам вызов и улучшаете локальность кеша кода. Иногда это может привести к огромному росту производительности. Специально в 1 строке функций доступа к данным, например, аксессоров, используемых в объектно-ориентированном коде.

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

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

Почему?

Пример: в файле заголовка inlinetest.h

int foo();
inline int bar();

В блоке компиляции inlinetest.cpp

 int foo(){ int r = bar(); return r; }


 inline int bar(){ return 5;};

Затем на main.cpp

 #include "inlinetest.h"
 int main()
 {
  foo();
 //bar();
  }

Скомпилируйте один объектный файл за раз. Если вы раскомментируете этот "бар", у вас будет ошибка. Поскольку встроенная функция реализована только в объектном файле inlinetest.o и не экспортируется. В то же время функция foo, скорее всего, вложила в нее код функции бара (поскольку bar является одиночной линией без операции ввода-вывода, то ее очень вероятно быть встроенным)

Но если в файле заголовка вы объявили встроенную функцию и внедрили ее в строку, вы сможете использовать ее в любом модуле компиляции, который включает этот заголовок. ( "образец кода" );

Удалить ключевое слово inline, и компилятор НЕ приведет к ошибке даже при вызове bar в главном И не будет встроенного, если вы не попросите компилятор встроить все функции. Это не стандартное поведение большинства компиляторов.