пятница, 15 октября 2010 г.

Inline. Встроенные функции.

Раз уж в 16 вопросе были упомянуты встроенные функции, думаю, хорошо было бы рассказать о них подробнее. Как уже сказано, компилятор будет пытаться заменять вызовы таких функций непосредственно на их определения. Например:

inline int plusOne(int n){
  return n+1;
}
/*...*/
int k=5;
cout << plusOne(k);
 

Компилятор заменит plusOne(k) на (k+1), подставив k вместо n в определении функции. Рассмотрим более интересный пример:

//рекурсивное вычисление факториала:
inline int fact(int n){
  return n!=1 ? n*fact(n-1) : 1;
}
/*...*/
cout << fact(3);
 

Действия компилятора с этим выражением по шагам:
  1. cout << (3!=1 ? 3*fact(3-1) : 1); //заменил вызов определением
  2. cout << 3*fact(2); //наш компилятор не дурак - упростил выражение
  3. cout << 3*(2!=1 ? 2*fact(2-1) : 1); //заменил
  4. cout << 6*fact(1); //упростил
  5. cout << 6*(1!=1 ? 1*fact(1-1) : 1); //вызов fact уже не нужен, так как условие не выполняется.
  6. cout << 6;
Теперь такое выражение:
cout << fact(100);
 

Что будет делать компилятор? Заменять вызов 100 раз? А если написать fact(1000)? А если так:
int k;
cin >> k;
cout << fact(k);
 

Опять рассмотрим по шагам:
  1. cout << (k!=1 ? k*fact(k-1) : 1); //Это уже не упростить. Ладно, заменим fact(k-1)
  2. cout << (k!=1 ? k*(((k-1)!=1 ? (k-1)*fact(k-2) : 1)) : 1); //Нда... Продолжаем?
  3. cout << (k!=1 ? k*(((k-1)!=1 ? (k-1)*(((k-2)!=1 ? (k-2)*fact(k-3) : 1)) : 1)) : 1);

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

Комментариев нет:

Отправить комментарий

Можно использовать теги <b>, <i>