inline function
: 함수의 호출부에 함수의 기계어 코드로 치환되는 함수
매크로 함수는 함수의 호출처럼 보이지만 전처리계 과정에서 치환되는 것일 뿐이다.
매크로 함수의 단점으로 단항연산자(++) 을 정상적으로 처리하지 못한다.
인라인 함수는 디버깅 모드나 컴파일러 최적화 옵션을 설정해주지 않으면 동작하지 않는 단점이 있다.
인라인 함수가 동작하지 않는 조건(컴파일러가 인라인 함수를 무시하는 경우)
1) 재귀 호출
2) 함수 포인터 사용 시
3) 함수의 기계어 코드 크기가 매우 큰 경우, 컴파일러가 inline으로 실행하지 않음
전통적으로 C언어 개발자들은 함수 호출에 따른 오버헤드를 줄이기 위해서 매크로를 사용한다.
의 결과는 어떻게 될까?
9라고 예상하기 쉽지만, 12 혹은 16 으로 출력된다.
처럼 3이 전달되고 3 * 3 연산이 진행될 것으로 예상할 수 있으나,
으로 치환된다.
결과적으로 매크로 함수는 위와 같은 단항연산자의 문제를 해결할 수 없다는 문제점이 있다.
C++ 에서는 매크로 함수를 전처리기가 실행하는 것이 아니라, 컴파일러가 실행하도록 변경하였다.
inline 함수가 이렇게 동작한다.
위 코드는 add 함수와 달리 함수의 기계어 코드가 남게 된다.
add 함수는 asm 코드를 확인해보면 call add 를 호출하게 되는데,
inline_add 는 inline 함수이므로 컴파일러가 해당 line 을 기계어 코드로 변경하게 된다.
한 가지 주의할 점은, inline 함수를 사용하려면 컴파일 최적화 옵션을 주어야 한다.
Visual studio 개발 환경에서는 아래와 같이 cl 호출 시 옵션을 /Ob1 을 줘야 한다.
C:\ cl inline_function.cpp /FAs /Ob1
혹은 visual studio 에서는 project > 속성 > c/c++ > 최적화 에서 설정할 수 있다.
결론적으로,
인라인 함수는 함수의 호출 자리에 기계어 코드로 치환되는 함수를 의미한다.
장점 : 인라인 함수는 전처리기가 아닌 컴파일에 의해 처리되므로 매크로의 효율성은 그대로 유지하면서 코드의 안전성은 높아지게 된다.
단점 : 자칫 목적 파일의 크기가 커질 수 있으므로, 함수의 구조가 간단한 경우에만 사용하는 것을 권장한다.
하지만 inline 함수가 적용되지 않는 한 가지 경우가 있다.
재귀 함수의 경우 inline 함수가 적용되지 않는다.
또 한 가지 inline 함수가 적용되지 않는 예를 살펴보자.
foo(), goo() 함수 호출 시 아래와 같은 기계어 코드로 변경된다.
call 로 호출이 되냐 안되냐에 차이가 있는데
inline function 은 call 명령어를 사용하지 않는다.
(call 명령어는 instruction pointer에 있는 내용을 stack 에 넣고(push) 해당 주소로 jump 한다.)
하지만 function pointer의 경우 runtime 에 언제든지 변경될 수 있으므로,
컴파일러가 이것이 inline function 을 가리킬지 일반 함수를 가리킬지 확신할 수 없다.
따라서 function pointer 의 경우 inline function 을 가리키게 해도 inline 으로 치환되지 않는다.
Summary
1. 인라인 함수는 함수 호출 명령이 함수 코드로 확장되는 함수
2. 일반적으로 컴파일러는 인라인 명령을 수행하지 않으며 최적화 옵션을 통해 실행될 수 있다.
3. 함수 호출로 인한 성능 저하가 없으며 매크로 함수보다 안전하다.
4. 목적 파일의 크기가 커질 수 있으므로 가급적 짧은 함수에 사용하는 것이 좋으며
목적 파일의 크기가 오히려 작아질 수 있다.
5. 경우에 따라서 컴파일러가 인라인 명령을 무시할 수도 있다.
e.g, 크기가 매우 큰 함수, 재귀 호출, 함수 포인터 사용 등
피드 구독하기:
댓글 (Atom)
[C++] meta programing
재귀 호출에 관해 template meta programming 을 적용한 예제를 살펴보자. #include using namespace std; int fact(int n){ if(n factorial 연산을 하는 일반적인 재귀 호출 함...
-
Smart Pointer : 포인터처럼 동작하며 자동으로 메모리를 해제하고 안전하게 resource를 관리하도록 돕는 객체 포인터는 소멸자가 호출되지 않아 memory leak이 발생한다. Java, C#같은 VM이 있는 언어는 VM에서 G...
-
nullptr 란? C++11 에서 지원하는 null pointer 상수 먼저 pointer 가 초기화될 수 있는 정수 값을 살펴보자. 정수 0은 모든 타입의 포인터에 암시적 형변환을 통해서 초기화 값으로 사용될 수 있다. 하지만 그 이...
-
자료 구조를 순회하여 데이터에 접근하는 방법을 살펴보자. Container 에 저장된 데이터에 접근하기 위해 대표적으로 Iterator의 begin(), end() function 을 사용한다. 하지만 위 예제에서 show() 함수에 배열이...
댓글 없음:
댓글 쓰기