본문 바로가기

C++

[C++] 인라인 함수의 장단점, #define 매크로와 차이

0. 인라인 함수의 개념

  • C++ 언어에서 코드의 효율성을 고려하여 만들어진 기능이다.
  • 인라인 함수는 함수 호출 오버헤드를 감소시킨다.
  • 인라인 함수가 호출되면, 인라인 함수의 전체 코드가 인라인 함수 호출 시점에 삽입되거나 대체된다.

 

1. 인라인 함수의 기본적인 형태

inline return_type func_name(parameters)
{
	//function code
}

 

 

2. 인라인 함수 호출 예제

#include <iostream>
using namespace std;

inline void print(void)
{
	cout << "This is inline Fuction" << endl;   
}

void main()
{
	print();
}

이러면 출력 결과로 "This is inline Function"이 호출된다.

그저 inline함수와 일반 함수의 호출법은 차이가 없다. 하지만 내부적으로 실행되는 형태가 다르다.

일반 함수의 경우 함수의 주소를 이용해서 호출하지만,

inline 함수의 경우, main()함수 내에 코드가 직접 써져 있는 것과 같은 효과를 얻는다.

즉, 함수 호출에 대한 오버헤드가 줄어든다.. 그것은 성능 향상을 의미한다. 

 

 

3. 인라인 함수의 장점

  • 인라인 함수의 전달인자에 데이터형을 체크할 수 있다.
  • 매크로가 갖는 부작용 없이 일반 함수처럼 사용이 가능하다.
  • 디버깅이 가능하다. 즉, 현재 변수에 어떤 값이 들어가 있는지 알 수 있다.
  • 함수 호출 오버헤드가 발생하지 않는다.
  • 컴파일러가 함수 본문에서 컨텍스트별 최적화(context optimization)를 수행할 수 있다.

 

4. 인라인 함수의 단점

  • 실행 코드가 커진다.
  • 인라인 함수의 구현을 짧게 1~3줄 정도의 짧은 코드로 작성한다. (길면 캐시 적중률이 감소한다.)
  • 구현이 길어진다면 컴파일러는 인라인 함수를 일반 함수로 취급하게 된다.
  • 인라인 함수를 자주 사용하면, 같은 코드의 중복으로 바이너리 실행 파일이 커진다.
  • 인라인 함수가 변경된다면, 전체 코드가 그 변경사항을 반영해야 하므로, 컴파일 시간 오버헤드가 발생한다.

 

5. 컴파일러가 인라인 함수를 무시하는 경우

  • 함수에 루프가 포함되어 있을 때 (for, while, do-while)
  • 함수에 정적 변수들이 있을 때 (static variables)
  • 함수가 재귀호출을 할 때
  • 함수가 switch나 goto문이 포함될 때

 

6. Inline 함수의 올바른 사용법

#include <iostream>
using namespace std;
class operation
{
	int a, b, add;
	
public:
	void get();
	void sum();
};

inline void operation::get()
{
	cout << "Enter first value : ";
	cin >> a;
	cout << "Enter second value : ";
	cin >> b;

}

inline void operation::sum()
{
	add = a + b;
	cout << "두 수를 더한 결과는 : " << add << endl;

}

int main()
{
	operation s;
	s.get();
	s.sum();

}

operation이라는 클래스에서 get(), sum()을 먼저 선언을 해주고, 그다음 inline함수를 구현하였다.

inline함수로만 바로 구현해도 되지만, 이것은 프로그래밍의 좋지 않은 습관이다.

좋은 프로그래밍 습관은 인터페이스처럼 함수를 선언해두고, 인라인에서 함수를 구현하는 것이다.

 

 

7. 인라인 함수와 #define 매크로와 기능 비교

#include <iostream>
using namespace std;
#define MAX(A,B)(A>B)?A:B

inline int max(int a, int b)
{
	if (a > b)
		return a;
	return b;
}

void main(void)
{
	int x = 10, y = 20, m;
	m = MAX(x++, y++);
	cout << "x= " << x << ", y= " << y << ", m= " << m << endl; //매크로를 이용한 경우 
	//값은 x=11, y=22, m=21 
	
	x = 10, y = 20;
	m = max(x++, y++);
	cout << "x= " << x << ", y= " << y << ", m= " << m << endl; //인라인을 이용한 경우
	//값은 x=11, y=21, m=20
}

같은 코드지만 매크로의 경우 m 값이 21, inline의 경우 m은 20이 나왔다.

매크로의 경우 m=(x++)>(y++)?x++:y++의 형태였고, (x++)>(y++)가 진행된 다음에는 11, 21이 됐을 것이고,

삼항 연산자로 y값이 더 컸으므로 false 값으로 y++로 들어갔을 것이다. 그래서 y 값은 22가 됐을 것이다.

m이 21이 된 이유는 m이 출력되고 난 후에, y값이 1 증가하므로 m이 출력될 때에는 y값은 21이다.

 

이처럼 매크로의 치환은 부작용을 야기할 수 있으나, 인라인 함수로 재구성하면 부작용을 없앨 수 있는 단편적인 예시였다.

 

 

 

참고사이트

https://www.geeksforgeeks.org/inline-functions-cpp/

C++ 프로그래밍 입문서의 결정판 프로그램과 STL 이창현 지음