Преимущества объявления функции как "встроенной"?

Каждый раз, когда я читал о "встроенной" декларации в C, упоминается, что это только подсказка компилятору (т.е. не должны подчиняться ему). Есть ли какая-нибудь польза для его добавления, или я должен просто полагаться на компилятор, знающий лучше меня?

Ответ 1

Есть две причины использовать ключевое слово inline. Один из них - подсказка для оптимизации, и вы можете смело игнорировать его; ваш компилятор, как и игнорировать его. Другая причина заключается в том, чтобы позволить функции существовать в нескольких единицах перевода, и это использование строго необходимо. Если вы помещаете функцию в заголовочный файл .h, например, вы должны объявить ее встроенной.

Ответ 2

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

Ответ 3

В целом современные компиляторы будут "встроенными" вещами, которые они считают важными. Я бы позволил ему справиться с этим для вас.

Edit:

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

Ответ 4

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

Например, на моей платформе я измерил разницу между встроенной и прямой (невиртуальной) функцией как около 5 наносекунд, поэтому мое эмпирическое правило заключается в том, что я встроенные функции, которые должны занимать менее десяти циклов: тривиальные аксессоры и как. Другие специфические функции впоследствии включаются, когда мой профилировщик говорит мне, что я трачу много времени на накладные расходы, называя их.

Ответ 5

С++ FAQ имеет хорошую информацию об этом. Я предпочитаю использовать встроенную функцию, поскольку она дает компилятору больше информации о том, что мне "нравится" делать. Независимо от того, заканчивается ли компилятор, он зависит от него, но небольшая помощь не повредит.

Ответ 6

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

Компилятор не является профилировщиком.

Ответ 7

Разница вряд ли имеет значение.

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

Ответ 8

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

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

Ответ 9

Декларация в значительной степени бесполезна и сильно отличается от первоначального намерения. Составители взяли гораздо больше свободы, что и что не встраивать (IMO).

Это подсказка для компилятора, использующая его, поможет вам и имеет предполагаемое значение только иногда.

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

Вложение не является серебряной пулей для повышения производительности; это может иметь негативные последствия. Злоупотребление inlining может иметь некоторые страшные последствия в крайних случаях, но обычно производительность немного хуже, а двоичные файлы больше при неправильном использовании. Правильное использование вставки может иметь значительно положительные результаты.

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

Другое дело: у вас будет другая связь с С++.

Ответ 10

Он обеспечивает простой механизм, позволяющий компилятору применять больше ОПТИМИЗАЦИЙ.
Встроенные функции быстрее, потому что вам не нужно нажимать и вставлять вещи в/из стека, как параметры и обратный адрес; однако, это делает ваш двоичный файл немного большим.

Значительно ли это имеет значение? Не очень заметно на современном оборудовании для большинства. Но это может иметь значение, чего достаточно для некоторых людей.

Маркировка чего-то встроенного не дает вам гарантии, что она будет встроенной. Это просто предложение компилятору. Иногда это невозможно, например, когда у вас есть виртуальная функция или когда есть рекурсия. И иногда компилятор просто решает не использовать его. Я мог видеть такую ​​ситуацию, которая обнаруживала бы заметную разницу:

inline int aplusb_pow2(int a, int b) {
  return (a + b)*(a + b) ;
}

for(int a = 0; a < 900000; ++a)
    for(int b = 0; b < 900000; ++b)
        aplusb_pow2(a, b);