본문 바로가기

Language/C++ 그때그때 끄적끄적

[C++]inline 함수와 매크로 함수

inline 키워드는 함수를 호출할 때 발생하는 오버헤드를 줄이기 위해 함수가 호출되는 대신 함수가 호출되는 곳마다 함수의 코드를 복사해 넣어주는 방법입니다

오버헤드는 무언가를 처리할때 드는 추가적인 시간을 말합니다

함수 호출의 과정은 아래와같습니다

  1. 함수의 인자를 스택에 저장
  2. 함수가 리턴될 때 돌아올 주소를 스택이나 레지스터에 저장
  3. 함수의 시작 주소로 점프
  4. 함수의 코드 실행
  5. 함수에서 만들어진 지역변수, 스택에 저장된 인자 해제, 리턴 값을 레지스터에 저장
  6. 함수를 호출할 때 저장해둔 주소로 돌아감

이러한 과정 속에서 오버헤드가 발생하게 됩니다 간단한 함수도 이러한 과정을 거치기 때문에 이러한 오버헤드를 줄이기 위해 inline이라는 키워드를 사용하게 됩니다 하지만 함수 코드가 복제되기 때문에 실행파일의 크기가 커진다는 단점이 있습니다.

사실 컴파일러는 자동으로 함수의 인라인화를 진행합니다 인라인 키워드를 사용하지 않아도 컴파일러의 성능을 고려하여 자동으로 함수를 인라인화 시키며, 인라인 키워드를 사용한 함수 또한 자유로게 무시할 수 있습니다.(길이가 긴 함수를 인라인화 하려고 하면 무시할 수 있습니다.) 때문에 inline 함수는 권장사항일 뿐 굳이 사용할 필요가 없습니다.

PS. __forceinline 키워드는 컴파일러를 무시하고 프로그래머의 판단하에 사용되는 인라인 함수입니다 __forceinline 키워드를 사용해도 강제로 인라인 못 시키는 경우가 있긴 합니다 때문에 간단하고 짧은 함수를 인라인 시킬 때만 사용하도록 해야 합니다.

 

매크로 #define는 치환을 해주는 지시어입니다 단순히 치환으로 사용할 때와 매크로 함수로 사용할 때의 형태가 조금은 다른데요

#define [정의] [상수]

해당 형식으로 매크로를 사용할 시 코딩할 때 최대치 정의와 같은 특정 상수를 지속적으로 사용해야 할 때 우리가 지정한 정의를 사용해서 상수를 대신할 수 있습니다

#define MAX 100

int* arr = new int[MAX];

매크로 함수로 사용할 경우 함수의 역할을 대신하여 파라미터 값을 받을 수 있고 반환도 하지만 반환 형태가 그저 치환의 형태를 뛰고 있기에 우리가 예상한 코드와 조금 다를 수 있습니다.

#define mul(a,b) a*b

cout << mul(10,20) << '\n';			// 200

cout << mul(10+3,20+2) << '\n';		// 72
// 13 * 22 = 286 이 출력될거라는 예상과는 다르게 72가 출력되었다
// 매크로 함수는 단순 치환을 하기때문에 
// 10 + 3 * 20 + 2 = 72로 출력이된것이다

매크로 함수는 전처리기에서 inline함수는 컴파일리에서 처리됩니다

inline은 데이터 타입을 정의하지만 매크로는 그렇지 않습니다(단순 치환)