답변:
첫째, inline
함수 의 스펙은 힌트 일뿐입니다. 컴파일러는 inline
한정자의 유무를 완전히 무시할 수 있으며 종종 무시합니다 . 즉, 상기와 더불어, 컴파일러 수 는 무한 루프 언 롤링 수만큼 재귀 함수를 인라인. 단순히 기능을 "롤"할 수있는 수준에 제한을 두어야합니다.
최적화 컴파일러는 다음 코드를 사용할 수 있습니다.
inline int factorial(int n)
{
if (n <= 1)
{
return 1;
}
else
{
return n * factorial(n - 1);
}
}
int f(int x)
{
return factorial(x);
}
이 코드로 :
int factorial(int n)
{
if (n <= 1)
{
return 1;
}
else
{
return n * factorial(n - 1);
}
}
int f(int x)
{
if (x <= 1)
{
return 1;
}
else
{
int x2 = x - 1;
if (x2 <= 1)
{
return x * 1;
}
else
{
int x3 = x2 - 1;
if (x3 <= 1)
{
return x * x2 * 1;
}
else
{
return x * x2 * x3 * factorial(x3 - 1);
}
}
}
}
이 경우 기본적으로 함수를 3 번 인라인했습니다. 일부 컴파일러 는 이 최적화를 수행합니다. MSVC ++는 재귀 함수 (최대 20 개)에서 수행 될 인라인 레벨을 조정하는 설정을 가지고 있습니다.
실제로 컴파일러가 지능적으로 작동하지 않으면 inline
d 함수의 사본을 재귀 적으로 삽입 하여 무한히 큰 코드를 작성 하려고 할 수 있습니다 . 그러나 대부분의 최신 컴파일러는이를 인식합니다. 그들은 다음 중 하나를 수행 할 수 있습니다.
사례 2의 경우 많은 컴파일러 #pragma
에서이 작업을 수행 할 최대 깊이를 지정하도록 설정할 수 있습니다. gcc 에서는 명령 행에서이 정보를 전달할 수도 있습니다 --max-inline-insns-recursive
(자세한 내용은 여기 참조 ).
이것이 일반적으로 작동하지 않는 이유는 이미 제공된 답변을 참조하십시오.
"각주"로서 템플릿 메타 프로그래밍을 사용하여 찾고있는 효과를 얻을 수 있습니다 (적어도 예제로 사용중인 계승에 대해서는) . Wikipedia에서 붙여 넣기 :
template <int N>
struct Factorial
{
enum { value = N * Factorial<N - 1>::value };
};
template <>
struct Factorial<0>
{
enum { value = 1 };
};
"컴파일러는 함수를 인라인할지 여부를 어떻게 결정합니까?"
컴파일러, 지정된 옵션, 컴파일러의 버전 번호, 사용 가능한 메모리 양 등에 따라 다릅니다.
프로그램의 소스 코드는 여전히 인라인 함수에 대한 규칙을 따라야합니다. 함수가 인라인되는지 여부에 관계없이 함수가 인라인 될 가능성을 준비해야합니다 (일부 알려지지 않은 횟수).
재귀 매크로는 일반적으로 불법적 인 것으로 보이며 정보가 잘못되었습니다. C 및 C ++는 재귀 적 호출을 방지하지만 재귀적인 것처럼 보이는 매크로 코드를 포함하여 변환 단위는 불법이되지 않습니다. 어셈블러에서 재귀 매크로는 일반적으로 합법적입니다.