2016-05-12 5 views
0

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

+5

Во время компиляции – ForceBru

+0

Я думаю, что вам не хватает одной важной детали: встроенная функция означает, что вызов функции не требуется. – molbdnilo

+0

Возможный дубликат [Является ли инкрустация выполненной во время компиляции или во время выполнения?] (Http://stackoverflow.com/questions/18862971/is-inlining-done-at-compile-time-or-run-time) –

ответ

1

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

0

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

Например, возьмем следующее:

#include <iostream> 
using namespace std; 

inline int max(int a, int b) 
{ 
    return a > b ? a : b; 
} 

int main() 
{ 
    cout << max(5,9) << endl; // "9" 
    return 0; 
} 

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

int main() 
{ 
    cout << (5 > 9 ? 5 : 9) << endl; 
    return 0; 
} 

Таким образом, он все еще работает (5 больше, чем 9? И т. Д.), И закончит печать 9, но ему не нужно делать вызов функции.

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

#define MAX(a,b) ((a)>(b) ? (a) : (b)) 

В качестве макроса. Если были использовать

int a=5; 
int b=9; 

cout << MAX(a++, b++) << endl; // "10" 
cout << a << ' ' << b << endl; // "6 11" 

Мы ожидаем a и b для печати 6 и 10 соответственно. Однако, в макросе, это замещено, как

((a++)>(b++) ? (a++) : (b++)) 

Когда это называется, мы будем иметь пост-приращения в раздел (a++)>(b++), который даст a=6 и b=10. Затем мы выполняем оператор if и запускаем (b++) (условие else), которое затем дает b=11, что еще больше, чем ожидалось.

Используя inline, мы получим ожидаемый результат, так как он выполнит эти приращения после выполнения оператора.

int a=5; 
int b=9; 

cout << max(a++, b++) << endl; // Inline: "9" 
cout << a << ' ' << b << endl; // "6 10" 
+1

Это является функционально-подобным макросом, который является заменой текста. С помощью этой встроенной функции 'max (a ++, b ++)' будет оценивать 'a ++' и 'b ++' только один раз, в то время как один будет оцениваться дважды, если используется замена текста. По этой причине встроенные функции считаются более безопасными, чем макрос-функции. – MikeCAT

+0

Точно. Он похож на макросы, но гораздо безопаснее. – mojo1mojo2

+0

Позаботьтесь, чтобы объяснить, какая часть моего ответа заслуживает понижения? – mojo1mojo2

3

на время компиляции связывания происходит и во время выполнения исполнения происходит

Не совсем.

В сборках времени, три этапа происходит:

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

    Никакой обработки нетекстовой обработки (это ничего не понимает в структуре или значении программы).

  2. Компилятор анализирует блок перевода и испускает код объекта.

    Включает оптимизацию до, во время и после генерации кода. Функция inlining традиционно является одной из этих оптимизаций, так как это происходит, когда генерируется код сайта вызова.

  3. Ссылка linker связывает скомпилированные объектные файлы в исполняемый файл.

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

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

В любом случае, функция inlining выполняется во время сборки; это решение и сгенерированный код встроены в исполняемый файл.

Во время выполнения, когда вызов фактически выполняется, одна из двух вещей происходит:

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

  • компилятор выполнил вызов, а тело функционального кода присутствует, а выполнение просто продолжается (и через) его.

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


Обратите внимание, что эта модель компиляции не является универсальной. Например, в Java «объектный код» - это байт-код для виртуальной машины, а не собственный машинный код. Обычно это скомпилировано во время выполнения, что означает, что в процессе выполнения также могут выполняться встроенные и другие оптимизации.

+0

«Линкер не мог изменить это, потому что ему пришлось бы перезаписать исполняемый код, который не является его работой». Множество компиляторов теперь связывают генерирование временного кода как опцию, когда объектные файлы содержат представление кода, но окончательный код генерируется только во время ссылки, чтобы позволить _exectly_ такой вид оптимизации возникать, когда код «связан», , – jcoder

+0

Да, я сначала отказался от LTO, потому что я был обеспокоен тем, что OP не понимал разницу между временем компиляции и временем выполнения. – Useless

3

Технически говоря, рядный замена кода, если таковые имеются, должны иметь место во время компиляции, потому что:

  • Это вполне возможно сделать во время компиляции.
  • Если это происходит во время выполнения, вновь созданная часть кода должна быть снова скомпилирована для выполнения, что не имеет смысла.

Также обратите внимание, что нет гарантии, что вы получите что-то вроде «встроенной замены». Согласно N1570, 6.7.4 пункта 6:

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

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

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