본문 바로가기

프로그래밍/C++

[C++] 인라인과 인라인 함수

들어가며

이번 시간에는 '인라인' 에 대하여 알아볼 생각이다.

인라인이라고 하면 무엇이 생각나는가?

그렇다! 모두가 알고, 땅이 알고, 하늘이 아는, 바로

'인라인 함수'다!

혹시 '인라인 스케이트'를 생각하였는가?

그렇다면 정신차리자. 지금 우린 공부하기 위해 이곳에 있는 것이다.

 

Key Word - inline

한번 간지나게 영어로 표지글을 써봤다.

키워드 'inline'은 전에 배웠던 'macro'와 유사한 특징이 다수 존재한다.

우선 인라인 키워드를 사용하는 방법은 다음과 같다.

  • inline (Return Data type) (Function name) (Parameter Data type Parameter name)

한번 간지나게 영어로 써봤다.

이정도 쯤이야 현대를 살아가는 우리들에겐 모국어와 다름없지 않은가?

그렇다! 물론 아닐 뿐더러 나도 잘 모르겠다!

 

  • inline (반환값 자료형) (함수 이름) (매개변수 자료형 매개변수 이름)

이렇게 보니까 조금은 알아먹을 것도 같긴 한데 여전히 가독성은 절망에 가깝다.

어서 빨리 코드로 넘어가보자.

 

매크로와 인라인의 유사점

하지만 어림도 없다!

위에서 인라인과 매크로의 유사점을 언급한 바 있다.

우린 이 점을 먼저 짚고 넘어가야 한다.

자, 매크로가 전처리기 과정을 거치면 코드에 어떤 변화가 있었는지 기억해 낼 필요가 있다.

바로, 함수의 몸체가 함수의 호출문을 대신했다는 것이다.

예를 들어 아래와 같은 코드가

#include <iostream>

#define SQUARE(x) ((x)*(x))                 // 함수의 몸체

int main ()
{
    std::cout << SQUARE(5) << std::endl;    // 호출문으로
    return 0;
}
#include <iostream>

#define SQUARE(x) ((x)*(x))

int main ()
{
    std::cout << ((5)*(5)) << std::endl;    // 대체되었다.
    return 0;
}

위 코드처럼 바뀌는 것을 의미한다.

이처럼 함수의 몸체가 함수 호출문을 완전히 대체하였을 때,

함수가 인라인화 되었다고 한다.

 

매크로의 장점과 인라인의 연관성

우린 매크로 함수의 장점과 단점을 잘 알고 있다.

모르겠다면 이 블로그에 있는 매크로 함수 관련 글을 보고 오도록 하자.

간단하게 정리하면 다음과 같다.

  • 장점: 타 함수와 상대적으로 실행속도의 이점이 있다.
  • 단점: 정의하기가 까다롭고, 복잡한 매크로 함수를 정의하는데 한계가 있다.

그렇다면 우린 이런 생각을 해볼 수 있다.

"아 매크로 함수 장점만 꿀빨고 단점은 손절하고 싶따!!!"

모든 일에는 손익이 있기 마련인데 어떻게 이익만을 취하고 나쁜것은 가지지 않으려고 하는,

그런 책임감 없는 태도와 이기심만 가지는가!

생각해보면 이런 도둑놈 심보가 인류를 발전시켜 왔음을 알 수 있다.

물론 리스크는 낮추고 효율은 높이는 방향으로 말이다.

그리고 그 어려운 것을 해내는 것이 'C++의 인라인 함수'이다.

 

인라인의 정의 방법

인라인 함수의 정의 방법은 다음과 같다.

#include <iostream>

inline int SQUARE (int x)       // inline 선언으로 SQUARE함수가 인라인화 되었다.
{
    return x*x;
}

int main ()
{
    std::cout << SQUARE(5) << std::endl;    // 25
    std::cout << SQUARE(12) << std::endl;   // 144
    
    return 0;
}

매크로를 이용한 함수의 인라인화'전처리기'에 의해서 처리되지만,

'inline'을 이용한 함수의 인라인화'컴파일러'에 의해서 처리된다.

따라서 컴파일러가

"??? 뭐야 이거? 인라인 왜 여기 있어? 성능 떨어지니까 인라인 안 해야지;; 아 뭐야;;;"

라고 판단한 경우 이 키워드를 무시하기도 한다. 또한,

"어? 이 함수 이거 인라인화 해버리면 오히려 더 좋을 거 같은데?"

라고 판단하는 경우 일부 함수를 임의로 인라인 처리하기도 한다.

아주 지 멋대로다.

고맙게도 말이다.

 

인라인 함수의 메커니즘

자 일단 아래의 코드를 구성하였다고 가정하자.

#include <stdio.h>

inline int add(int a, int b)    // 인라인 함수로 정의
{
    return a + b;
}

int main()
{
    int num;

    num = add(10, 20);    // 인라인 함수 호출

    printf("%d\n", num);  // 30

    return 0;
}

자 이제 실행을 해보고 일반 함수와 어떤 것이 다른지 생각해 보자.

알 수 없는가? 다시 한번 생각해 보도록 하자. 그래도 모르겠는가?

그렇다! 실행 결과만 가지고는 일반 함수와 인라인 함수의 메커니즘을 구분할 수 없다.

일반 함수의 경우에는 함수를 '호출'하며,

인라인 함수의 경우는 함수를 '복제'하는 것이다!

<출처> 코딩도장, Unit 85.14 인라인 함수 사용하기, 그림 85-4

따라서 함수의 호출 과정이 없으므로 위에서 말한 바와 같이 실행 속도에 있어서 이점이 있다.

그러므로 인라인 함수는 자주 호출되면서 속도가 중요한 부분에서 주로 활용된다.

하지만 단점도 물론 존재하는데, 함수 코드가 복제되는 것이므로 인라인 함수를 과도하게 많이 사용할 경우

실행 파일의 크기가 커질 수도 있으니 주의하여 적재적소에 사용할 필요가 있다.

 

매크로 함수에는 있지만, 인라인 함수에는 없는 장점

그런 것이 있다. 상식적으로 그럴 수도 있다고 생각한다.

"??? 야이 개ㅅ······. 아니 아까 전에는 매크로 함수에 있는 장점만 전부 다 꿀 빨 수 있다며!"

이런 도둑놈 심보를 보았나!

만약 그렇게 생각한 사람이 있다면 인류의 미래를 믿고 맡길 수 있을 거 같다.

잘 부탁한다. 그리고 '전부 다'라고 한 적은 없다.

인라인 함수는 매크로 함수의 장점을 완전히 대체하지 못 했다.

예를 들어 다음과 같은 함수가 있다고 가정하자.

#define SQUARE(x) ((x)*(x))

이 코드는 자료형에 의존적이지 않은 매크로 함수가 된다.

std::cout << SQUARE(12);    // int형 함수 호출
std::cout << SQUARE(3.14);  // double형 함수 호출

따라서 위의 함수 호출문은

std::cout << ((12)*(12));      // int형 함수 호출
std::cout << ((3.14)*(3.14));  // double형 함수 호출

위와 같이 변환이 이루어져서 어떠한 경우에도 데이터의 손실이 발생하지 않는다.

하지만 다음과 같은 인라인 함수의 경우에는 말이 달라진다.

inline int SQUARE (int x) { return x*x; }   // 정수형 매개 변수와 반환값

위와 같이 int형 기반으로 정의된 함수를 실수형으로다가 인자를 전달하면 어떤 일이 벌어지는가.

std::cout << SQUARE(3.14);   // 0.14가 손실되고 3*3의 결과인 9가 출력됨.

무려 소수점 이하가 누락되는 참사가 벌어져 데이터의 손실이 발생한다.

물론 이러한 문제점을 '함수의 오버로딩'을 통하여 충분히 해결할 수 있다.

하지만 여러 개의 함수를 사용하는 꼴이 되고, 한 번만 정의하면 되는 매크로 함수의 장점과는 거리가 멀어지게 된다.

그러나 C++의 '템플릿'이라는 것을 이용하면 매크로 함수와 마찬가지로 자료형에 의존적이지 않은 함수가 완성된다.

하지만 지금은 인라인에 관하여 알아보는 시간이니, 템플릿에 관한 것은 다음에 알아보도록 하자.

 

마치며

어떤가? 대강 '인라인'이라는 것에 대하여 감이 잡혔는가?

쉽게 생각하자. 매크로 함수의 장점을 끌어 쓰고 일반 함수의 특징으로 매크로 함수의 단점을 보완한,

그저 잘만 사용하면 도움이 되는 친구일 뿐이다.

그렇지 않다면 끔찍한 혼종에 불과하겠지만······.

아무튼  우리 모두 게으른 프로그래머가 되도록 노력하는 하루가 되었기를 바라며,


참고 및 출처

  • 코딩 도장

  • 윤성우 열혈 C++ 프로그래밍