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

Встроенные функции в С++

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

4b9b3361

Ответ 1

Да, функции, определенные внутри тела класса, неявно inline.

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

Ответ 2

Как указано другими, метод, определенный внутри класса, автоматически запрашивается в строке. Полезно понять, почему.

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

class A {
public:
  void f() { ... your code ... }
};

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

A__f_v:

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

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

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

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

рассмотрите этот встроенный код:

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

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

И, если вы случайно проходите в константах:

int c= add(5,4);

Он разрешен во время компиляции, и нет кода.

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

На другом конце спектра предположим, что вы запрашиваете строку в 1000 строк кода. Даже если ваш компилятор достаточно глуп, чтобы согласиться с ним, единственное, что вы сохраняете, - это сам вызов, и стоимость заключается в том, что каждый раз, когда вы его вызываете, компилятор должен вставить весь этот код. Если вы вызываете этот код n раз, ваш код увеличивается на размер подпрограммы * n. Таким образом, ничего большего, чем 10 строк, в значительной степени не стоит встраивать, за исключением особого случая, когда его называют только очень маленьким числом раз. Примером этого может быть частный метод, вызываемый только двумя другими.

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

Ответ 3

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

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

Ответ 4

Это действительно inlined - но любой встроенный запрос может быть проигнорирован компилятором.

Ответ 5

Это запрос компилятору, который он может игнорировать.

Ответ 6

В стандарте ISO С++ 2003 говорится:

7.1.2/2 Объявление функции (8.3.5, 9.3, 11.4) с встроенным спецификатор объявляет встроенный функция. Встроенный спецификатор указывает на реализацию, которая встроенная подстановка функции тело в точке вызова должно быть предпочтительнее обычного вызова функции
механизм. Реализация не является требуется для выполнения этого встроенного замена в точке вызова; однако, даже если этот встроенный замещение опущено, другое правила для встроенных функций в соответствии с пунктом 7.1.2 все еще соблюдаются.

7.1.2/3 Функция, определенная в определении класса, является встроенным функция. Встроенный спецификатор должен не отображается в функции масштаба блока декларация.

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

Ответ 7

Есть две вещи, которые нельзя объединить вместе:

  • Как вы отмечаете функцию как встроенную: определите ее с помощью строки в строке перед сигнатурой или определите ее в точке объявления;
  • Что компилятор будет рассматривать такую ​​встроенную маркировку: независимо от того, как вы пометили функцию как встроенную, она будет рассматриваться как запрос компилятором.