Вставка кода C++

есть ли разница в следующий код:

class Foo  
{
  inline int SomeFunc() { return 42; }
  int AnotherFunc() { return 42; }
};

будут ли обе функции вставлены? Действительно ли inline имеет значение? Есть ли какие-либо правила о том, когда вы должны или не должны встроенный код? Я часто использую AnotherFunc синтаксис (например, аксессоры), но я редко указываю inline напрямую.

9 ответов


обе формы должны быть вставлены одинаково. Inline является неявным для тел функций, определенных в определении класса.


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


гуру Саттера недели #33 отвечает на некоторые ваши вопросы и многое другое.

http://www.gotw.ca/gotw/033.htm


class Foo  
{
  inline int SomeFunc() { return 42; }
  int AnotherFunc() { return 42; }
};

правильно, что оба способа гарантированно компилируются одинаково. Однако предпочтительнее не делать ни того, ни другого. Согласно C++ FAQ вы должны объявить его обычно внутри определения класса, а затем определить его вне определения класса, внутри заголовка, с явным inline ключевое слово. Как описано в FAQ, это связано с тем, что вы хотите отделить объявление и определение для удобочитаемости других (объявление эквивалент "что" и определение "как").

действительно ли inline имеет значение?

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

есть ли какие-либо правила о том, когда вы должны или не должны встроенный код?

Я не знаю никаких жестких+быстрых правил, но ориентиром является только встроенный код, если он вызывается часто, и он относительно мал. Сеттеры и геттеры обычно встроены. Если он находится в особенно высокопроизводительной области кода, следует рассмотреть встроенную вставку. Всегда помните, что вы торгуете скоростью выполнения для исполняемого размера с помощью инлайнинг.


VC++ поддерживает __forceinline и __declspec (noinline) директивы, если вы думаете, что знаете лучше, чем компилятор. Подсказка: вы, вероятно, нет!


Inline является подсказкой компилятора и не заставляет компилятор встроить код (по крайней мере, в C++). Таким образом, короткий ответ-это компилятор и, вероятно, контекстно-зависимый, что произойдет в вашем примере. Большинство хороших компиляторов, вероятно, встроили бы оба, особенно из-за очевидной оптимизации постоянного возврата от обеих функций.

В общем inline не то, о чем вы должны беспокоиться. Это приносит преимущество производительности в том, что не нужно выполнять машинные инструкции для создания кадра стека и возвращение управления потоком. Но во всех случаях, кроме самых специализированных, я бы сказал, что это тривиально.

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

конкретные приложения и архитектуры также могут привести вас к встраиванию в качестве оптимизация.


Я нашел некоторые компиляторы C++ (т. е. SunStudio) жалуются, если inline опущен, как в

int AnotherFunc() { return 42; }

поэтому я бы рекомендовал всегда использовать ключевое слово inline в этом случае. И не забудьте удалить ключевое слово inline если вы позже реализуете метод как фактический вызов функции, это действительно испортит связывание (в SunStudio 11 и 12 и Borland C++ Builder). Я бы предложил минимальное использование встроенного кода, потому что при прохождении кода с отладчиком он будет "шаг в" встроенный код даже при использовании команды "шаг через", это может быть довольно раздражающим.


обратите внимание, что вне класса, inline делает что-то более полезное в коде: заставляя (ну, вроде) компилятор C++ генерировать встроенный код при каждом вызове функции, он предотвращает несколько определений одного и того же символа (подпись функции) в разных единицах перевода.

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

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

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


также добавить к тому, что сказал Грег, при предварительной оптимизации (т. е. inline-ing) компилятор консультируется не только с ключевыми словами в коде, но и с другими аргументами командной строки, указывающими, как компилятор должен оптимизировать код.