본문 바로가기
프로그래밍/키워드 정리

[C++] 복습용 키워드 정리 - 10

by Sik.K 2023. 4. 3.

<Template>

 

템플릿은 어떤 자료형이 들어올 지 모르지만, 같은 처리를 요구할 경우에 사용한다. 클래스와 함수에 사용이 가능하며 각각 클래스 템플릿, 함수 템플릿이라고 한다.

 

사용법은 간단하다. 템플릿이라 선언하고, 들어올 타입들을 총칭할 이름을 설정하고 그 이름으로 함수 혹은 클래스를 작성하면 끝이다.

 

template <typename T>
T add(T a, T b)
{
	return a + b;
}

위의 코드에서 어떤 자료형이 인자로 들어올 지 모르기 때문에 템플릿으로 함수를 작성하였다. 매개로 들어오는 자료형과 반환되는 자료형은 임의로 지정해둔 T라는 이름으로 되어 있다. 인자를 어떤 것을 넣냐에 따라 반환형이 달라진다.

 

int를 넣으면 int형으로 반환이 되고, float로 넣으면 float형으로 반환이 된다.

 

클래스 템플릿을 작성할 때도 위와 비슷하다.

 

template <typename T> // class T도 가능
class Calcu
{
private:
    T num1;
    T num2;
    
public:
    Calcu(T num1, T num2)
    {
        this->num1 = num1;
        this->num2 = num2;
    }
    
    T GetAdd()
    {
        return num1 + num2;
    }
};

int main()
{
     Calcu<int> calcu1(10, 20);
     cout << calcu1.GetAdd() << endl;
     
     Calcu<float> calcu2(10.0f, 20.0f);
     cout << clacu2.GetAdd() << endl;
}

단, 클래스 템플릿을 사용하기 위해선 선언 시에 어떤 자료형으로 만들 것인지 <> 안에 명시를 해주어야 한다.

 

그리고 템플릿에서 특정 자료형이 들어 왔을 때 다른 자료형과는 다른 결과물을 도출하고 싶을 경우에는 템플릿을 작성할 때 원하는 자료형을 명시해주고 작성을 해주면 된다.

 

template <typename T>
T sum(T a, T b)
{
	return a + b;
}

template <>
char* sum<char*>(char* s1, char* s2)
{
    char* str = "[char*]문자열을 더할 수 없습니다.";
    cout << "s1 : " << s1 << endl;
    cout << "s2 : " << s2 << endl;
    
    return str;
}

이처럼 템플릿으로 작성한 sum이라는 함수는 char* 형의 자료가 들어올 경우 기존의 결과물이 아닌 다른 결과물을 출력하도록 작성이 되었다.

 

또, 클래스 템플릿은 멤버 함수를 작성할 경우 헤더 파일에 작성을 해줘야 하며, 헤더를 벗어나면 오류가 발생한다. 멤버 함수의 정의를 할 때 클래스 내부에서 작성을 할 경우에는 문제가 없지만 헤더 파일 내부이지만 클래스 외부에서 작성을 할 경우 모든 함수마다 이 함수는 함수 템플릿임을 명시해야 한다.

 

클래스 템플릿을 상속할 경우에 부모 클래스로 상속이 가능하고, 자식 클래스로 상속 받을 수도 있다.

 

다만, 상속할 경우에는 자식 클래스를 작성할 때 부모 클래스인 클래스 템플릿이 어떤 자료형으로 들어가는 지 마찬가지로 <>를 이용해 명시해줘야 한다.

 

<인라인 함수>

 

inline 함수는 컴파일러가 함수를 호출하는 대신, 그에 대응하는 함수 코드로 대체하여 호출되는 모든 장소에 삽입할 것을 요청하는 것을 의미한다.

 

inline void PrintHello()
{
    cout << "Hello, World" << endl;
}

 

위와 같이 인라인 함수로 작성된 코드가 있다고 가정하자. 만약 특정 함수나 구문에서 저 함수를 호출하는 코드를 작성하면 컴파일러는 컴파일 과정에서 저 함수의 자리를 함수가 내포하고 있는 코드로 대체한다.

 

즉,

 

int main()
{
    PrintHello();

    return 0;
}

 

위의 PrintHello()의 자리가

 

int main()
{
    cout << "Hello, World" << endl;
    
    return 0;
}

로 대체됨을 의미한다.

 

이러한 인라인 함수의 장점은 무엇보다 빠른 속도에 있다. 함수는 호출될 때마다 스택에 쌓이고 작업을 처리한다. 만약 반환형이 존재하는 함수라면 함수 호출 시, 함수의 주소를 찾아가야 하고, 반환 되는 메모리의 주소도 알아야 하며, 그 함수가 스택에도 쌓이게 되니 상대적으로 느려지게 된다.

 

하지만 메모리 관리적 측면에서는 오히려 불리하다. 인라인으로 작성한다는 것은 즉 함수를 호출하는 모든 구문을 함수의 코드로 대체한다는 말이다. 코드를 절약해서 사용하기 위해 작성하는 함수로서의 장점이 무색해지고 그만큼 코드가 길어지니 메모리의 낭비가 생길 수 밖에 없다.

 

때문에 인라인 함수는 호출이 많이 일어나지 않는 함수이거나, 함수 내부 코드의 양이 매우 실행 속도가 짧은데 비해 함수의 호출 시간이 부담이 될 것이라 생각되는 상황에서만 인라인 함수로 만들어 사용하는 것이 합리적이다.

 

또한 인라인 함수는 매크로 함수와 동작방식, 결과에 대해 공통점이 많다.

댓글