티스토리 뷰

C++

inline 함수

취뽀가자!! 2019. 2. 24. 18:13

Inline 함수

lnline함수를 의역해보면 프로그램 코드라인 안으로 들어가 버린 함수라는 뜻이 된다. 여기서 잠시 Inline함수에 대해 알아보기 전에 매크로 함수에 대해 알아보겠다.

매크로 함수의 장점

매크로 함수의 대표적인 장점으로는 일반적인 함수에 비해서 실행속도의 이점이 있다는 점이다. 뿐만 아니라 매크로 함수는 성능향상에 많은 도움이 된다. 반면, 매크로 함수의 단점은 복잡한 함수를 매크로의 형태로 정의하는데 한계가 있다는 점이다.

매크로 함수를 예제 삼아 정의해 보면 다음과 같다.

1
2
3
4
5
6
7
#include <iostream>
#define SQUARE(x) ((x)*(x))
 
int main(void) {
    std::cout<<SQUARE(5)<<std::endl;
    return 0;
}
cs

위의 코드는 전처리 과정을 거치면 다음과 같이 변경된다. 여기서 중요한 점은 함수의 몸체부분이 함수의 호출문을 대체했다는 점이다.

1
2
3
4
5
6
#include <iostream>
 
int main(void) {
    std::cout<<((5)*(5))<<std::endl;
    return 0;
}
cs

위 예제와 같이 함수의 몸체부분이 함수호출 문장을 완전히 대체했을 때 함수가 인라인화 되었다라고 표현한다. 그런데 매크로 함수는 정의하기가 어려우니, 일반 함수처럼 정의가 가능하면 좋을것 같지 않은가?? 이 말은 즉, 매크로 함수의 장점은 유지하되, 단점은 제거하겠다는 뜻이다. 여기서 c++의 Inline 함수가 이와 같은 요구를 총족시켜 준다.

C++ 기반의 인라인 함수 정의

아래의 예제에서는 매크로 함수를 이용하지 않는, c++ 기반의 인라인 함수의 정의방법을 보이고 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
using std::cout;
using std::endl;
 
//인라인 함수의 정의방법을 보이고 있다. 키워드 inline의 선언을 통해서 함수 SQUARE는 인라인 함수가 되었다.
inline int SQUARE(int x) {
    return x*x;
}
 
int main(void){
    //SQUARE 함수를 호출하고 있다. 그런데 이 함수는 인라인 함수이니 몸체부분이 호출문을 대체하게 된다.
    cout<<SQUARE(5)<<endl;
    cout<<SQUARE(12)<<endl;
    
    return 0;
}
cs


참고로 매크로를 이용한 함수의 인라인화는 전처리기에 의해서 처리되지만, 키워드 inline을 이용한 함수의 인라인화는 컴파일러에 의해서 처리된다. 따라서 컴파일러는 함수의 인라인화가 오히려 성능에 해가 된다고 판단할 경우, 이 키워드를 무시해버리기도 한다. 또한 컴파일러는 필요한 경우 일부 함수를 임의로 인라인 처리하기도 한다.


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

매크로 함수는 자료형에 의존적이지 않는다. 하지만 inline함수의 경우 반환 타입을 지정해 주기 때문에 정해 놓은 타입으로만 사용이 가능하다. 물론, 오버로딩을 통해 해결할 수 있으나, 그렇게 되면 여러 개의 함수를 추가로 정의하는 꼴이 되니, 한번만 정의하면 되는 매크로 함수의 장점과는 거리가 멀어지게 된다. 그러나 c++의 템플릿이라는 것을 사용하면 매크로 함수와 마찬가지로 자료형에 의존적이지 않은 함수가 완성된다.

예제는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
using std::cout;
using std::endl;
 
template <typename T>
inline T SQUARE(T x){
    return x*x;
}
 
int main(void){
    cout<<SQUARE(5.5)<<endl;
    cout<<SQUARE(12)<<endl;
    
    return 0;
}
cs


인라인 함수와 헤더파일

만약 헤더파일과 소스파일을 나눠서 컴파일 할 경우 인라인 함수는 소스파일이 아닌 헤더파일에 넣어야 한다. 그 이유는 컴파일 과정에서 함수의 호출 문이 있는 곳에 함수의 몸체 부분이 삽입되어야 하기 때문이다.

아래는 예제이다.

헤더파일

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#ifndef __CARINLINE_H__
#define __CARINLINE_H__
 
#include <iostream>
 
using std::cout;
using std::endl;
 
namespace CAR_CONST {
    enum {
        ID_LEN = 20,
        MAX_SPD = 200,
        FUEL_STEP = 2,
        ACC_STEP = 10,
        BRK_STEP = 10
    };
}
 
class Car {
private:
    char gamerID[CAR_CONST::ID_LEN];
    int fuelGauge;
    int curSpeed;
public:
    void InitMembers(char *ID, int fuel);
    void ShowCarState();
    void Accel();
    void Break();
};
 
inline void Car::ShowCarState() {
    cout<<"ownerID: "<<gamerID<<endl;
    cout<<"연료량: "<<fuelGauge<<endl;
    cout<<"현재속도: "<<curSpeed<<endl;
}
 
inline void Car::Break(){
    if(curSpeed<CAR_CONST::BRK_STEP){
        curSpeed = 0;
        return;
    }
    curSpeed-=CAR_CONST::BRK_STEP;
}
 
#endif
cs

소스파일

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <cstring>
#include "CarInline.hpp"
 
using std::cout;
using std::endl;
 
void Car::InitMembers(char *ID, int fuel){
    strcpy(gamerID, ID);
    fuelGauge = fuel;
    curSpeed = 0;
};
 
void Car::Accel(){
    if(fuelGauge<=0)
        return;
    else
        fuelGauge-=CAR_CONST::FUEL_STEP;
    
    if((curSpeed+CAR_CONST::ACC_STEP)>=CAR_CONST::MAX_SPD){
        curSpeed = CAR_CONST::MAX_SPD;
        return;
    }
    curSpeed+=CAR_CONST::ACC_STEP;
}
 
cs

main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include "CarInline.hpp"
 
using std::cout;
using std::endl;
 
int main(void){
    Car run99;
    run99.InitMembers((char*)"run99"100);
    run99.Accel();
    run99.Accel();
    run99.Accel();
    run99.Accel();
    run99.ShowCarState();
    run99.Break();
    run99.ShowCarState();
    return 0;
}
 
cs

추가로, 이건 별개의 얘기이지만 인라인과 관련있기에 덧붙여본다. 구조체 안에 함수가 정의되어 있으면 그 함수는 인라인으로 처리해야 된다는 의미가 내포되어 있다. 따라서 인라인의 의미를 그대로 유지하려면 linline키워드를 통해 인라인 처리를 명시적으로 지시해야 한다.


---------------------------------------

이 글은 열혈 c++을 읽고 정리한 글 입니다.

'C++' 카테고리의 다른 글

const 이해하기  (2) 2020.11.19
정보은닉과 캡슐화  (0) 2019.03.03
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함