인라인(inline)은 C++ function keyword 중 하나로 함수 호출이 함수 자체의 내용 복사본으로 대체되어 실행된다.
마치 매크로처럼 행동하는 함수라고 생각하면 된다.
인라인 함수를 사용하면 다음과 같은 많은 이점을 얻을 수 있다.
일반적인 함수의 경우, 함수가 호출될 때마다 발생하는 일정량의 성능 오버헤드(overhead)가 있다는 단점이 있다.
오버헤드(overhead)
어떤 처리를 하기 위해 들어가는 간접적인 처리 시간, 메모리 등을 말한다.예를 들어 A라는 처리를 단순하게 실행한다면 10초 걸리는데, 안전성을 고려하고 부가적인 B라는 처리를 추가한 결과 처리시간이 15초 걸렸다면, 오버헤드는 5초가 된다.
또한 B를 개선해 B'라는 처리를 한 결과, 처리시간이 12초가 되었다면, 이 경우 오버헤드가 3초 단축되었다고 말한다
일반적인 함수에서 오버헤드가 발생하는 이유는 CPU가 다른 레지스터와 함께 실행 중인 현재 명령어의 주소를 저장해야 하므로(나중에 반환할 위치를 알 수 있도록) 모든 함수 매개 변수를 생성하여 사용하기 때문에 할당된 값을 사용하면 프로그램이 새 위치로 분기된다.
따라서, 일반적으로 함수를 호출하는 것보다 내부에서 작성된 코드(인스턴트 코드)가 훨씬 더 빠르다.
크거나 복잡한 태스크를 수행하는 함수의 경우 함수 호출의 오버헤드는 함수가 실행되는 데 걸리는 시간과 비교할 때 중요하지 않다.
그러나 작은 함수의 경우, 함수 호출에 필요한 시간이 실제로 함수 코드를 실행하는 데 필요한 시간보다 훨씬 많은 경우가 있어 이로 인해 상당한 성능 저하가 발생할 수 있다.
C++은 인라인 함수(inline function)라는 내부에서 작성된 코드의 속도와 함수의 장점을 결합하는 방법을 제공한다.
inline
키워드는 컴파일러에서 함수를 인라인 함수로 처리하도록 요청하여 컴파일러가 코드를 컴파일하면 모든 인라인 함수가 인-플레이스(in-place) 확장된다.
즉, 함수 호출이 함수 자체의 내용 복사본으로 대체되어 함수 오버헤드가 제거된다.
하지만 인라인 함수가 모든 함수 호출에 대해 적절한 위치에서 확장되므로 인라인 함수가 길거나 인라인 함수를 여러 번 호출하는 경우 컴파일된 코드를 약간 더 크게 만들 수 있다는 단점도 존재한다.
#include <iostream>
int min(int x, int y)
{
return x > y ? y : x;
}
int main()
{
std::cout << min(5, 6) << '\n';
std::cout << min(3, 2) << '\n';
return 0;
}
위 프로그램은 함수 min()
을 2번 호출하여 함수 호출 오버헤드를 2번 발생시킨다.
이런 간단한 min()
함수의 경우 인라인화 하기 좋다.
inline int min(int x, int y)
{
return x > y ? y : x;
}
이제 프로그램이 main()
을 컴파일하면 main()
이 아래와 같이 작성된 것처럼 기계 코드를 생성한다.
int main()
{
std::cout << (5 > 6 ? 6 : 5) << '\n';
std::cout << (3 > 2 ? 2 : 3) << '\n';
return 0;
}
이로 인해 더 빠르게 실행된다.
코드를 부풀릴 가능성이 있으므로 함수를 인라인화 하는 것은 내부 루프가 없는 짧은 함수에 가장 적합하다.
또한 inline
키워드는 권장 사항이며, 컴파일러(compiler)는 인라인에 대한 요청을 무시할 수 있다. (긴 함수를 인라인화 하려고 하면 무시할 가능성이 있다.)
마지막으로, 현대 컴파일러는 자동으로 함수를 인라인화 하는 데 매우 뛰어나다.
함수를 인라인으로 표시하지 않더라도 컴파일러는 성능이 향상될 것으로 생각하는 함수를 인라인화 한다.
따라서 대부분의 경우 inline
키워드를 사용할 필요가 없다.
결론
인라인 함수를 알고 있어야 하지만 최신 컴파일러는 함수를 적절하게 인라인화 하므로inline
키워드를 사용할 필요가 없다.