ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 함수 템플릿과 인라인 함수
    C++ 언어 2020. 3. 30. 17:01

    함수 템플릿이란?

    함수 템플릿은 함수의 다중 정의 기능의 단점을 보완 해주는 기능이다. 함수를 다중정의 할 경우 같은 이름의 함수를 반환값, 매개변수 등에 따라 다른 기능을 수행하는 함수로 만드는 것을 말한다. 따라서 함수를 다중정의 할 경우 같은 이름의 함수가 여러개 생기는 것이다.

    위와 같이 다중정의 함수를 사용한다면 사용자는 편의성과 확장성을 얻을 수 있지만 유지보수 측면에서 어려움을 겪는다. 예를 들어 다중정의 함수가 5개가 논리적 결함이 생긴다면 사용자는 5개 함수의 코드를 수정해야 할 것이다. 5개의 함수가 전부 사용되지 않는 다면 불필요한 코드가 생긴 것이며 메모리의 낭비로 이어진다. 이와같은 단점을 보완하기 위해 제공되는 기능이 함수 템플릿 이다.

    템플릿은 일종의 틀 이며 판화의 틀을 만들어 여러 장의 판화를 인쇄하는 것과 같다. 이때 인쇄하는 것이 소스코드인 것이다.

    template <typename T>

    반환형식 함수이름 (매개변수)

    템플릿은 위와 같은 형식으로 " template <typename T> " 와 같이 템플릿 자료형의 이름을 정한 뒤 일반 함수의 정의와 같이 정의하여 사용하면 된다.

     

    EX 

    // HelloNew_C+.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
    //
    
    #include "stdafx.h"
    #include<iostream>
    #include<cstdio>
    #include<string>
    
    template <typename T> // 사용할 템플릿 함수의 자료형 이름
    T add(T a, T b) // 템플릿 함수 반환 자료형 T, 템플릿 함수 매개변수 자료형 T 
    {
    	return a + b;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
    	std::cout << add(3, 5) << std::endl; // int 형식
    	std::cout << add(3.5, 5.5) << std::endl; // double 형식
    
    
    	return 0;
    }
    
    

    위와 같은 결과가 나오며 각 템플릿 함수가 호출 될 때 어떤 자료형으로 인식되는지 살펴보자

    1. int 자료형을 매개변수로 전달했을 때

    이와 같이 int 자료형의 매개변수와 반환값을 가지는 add함수가 Call 되어 Stack 메모리에 올려진 것을 확인 할 수 있다.

    2. double 자료형을 매개변수로 전달했을 때

    double 자료형의 메개변수와 반환값을 가지는 add함수가 Call 된 것을 볼 수 있다.

     

     

    inline 함수란 ?

    인라인 함수는 매크로의 장점 + 함수의 장점을 모아둔 함수이다. 예를 들어 함수 하나가 호출되면 호출되는 함수로 인해 생기는 오버헤드 ( 매개변수 복사, 스택 조정, 제어 이동 등등 ) 가 존재 할 것이다. 물론 함수가 매우 간단한 일을 수행하는 함수라고 해도 말이다. ex ) a + b 

    이와 같이 매우 간단한 일을 처리하는 동작의 반복을 줄이기 위해 해당 동작을 함수로 정의하여 함수를 사용한 다면 그로인해 생기는 오버헤드 문제가 있다. 이러한 단점을 해결 해 주는 것이 매크로이다. 매크로는 외형은 함수와 같지만 컴파일러는 매크로를 함수처럼 Call 하는 것이아니라 해당 매크로의 기술 된 내용을 소스코드에 똑같이 따라 친다고 보면 된다. 따라서 함수처럼 Call 되는 과정이 없어지며 소스코드에 사용자가 작성한 메크로의 동작이 기술된다.

    // HelloNew_C+.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
    //
    
    #include "stdafx.h"
    #include<iostream>
    #include<cstdio>
    #include<string>
    
    int fuction_add(int a, int b){
    	return a + b;
    }
    
    
    int _tmain(int argc, _TCHAR* argv[]){
    
    	int nTotal = 0;
    
    	nTotal = fuction_add(3, 4);
    	printf("%d", nTotal);
    
    	return 0;
    }

    위의 코드를 Debug 모드에서 컴파일하여 실행 시켜 보자 아래와 같은 어셈블리 코드로 번역된다.

    fuction_add 함수를 Call 하기 위해 매개 변수인 3, 4 를 스텍에 push 한 뒤 함수를 Call 하고 있다.  이제 프로그램의 흐름은 Call 된 함수로 넘어갈 것이다.

    위의 자료는 fuction_add 함수로 넘어온 어셈블리 코드이다. 실제로 호출 스텍에 함수가 올라가 있으며 해당 함수는add 하는 동작을 수행 후 함수를 반환하기 위해 Stack 메모리 영역의 내용을 하나씩 pop 하는 과정을 거쳐 마지막 으로 함수가 반환 된다. 이제 최적화 모드를 사용하여 해당 코드를 컴파일해 보자

    분명 fuction_add 함수를 작성하여 Call 하는 구문이 존재하지만 실제 동작을 보면 함수를 Call 하지 않으며 해당 함수의 매개변수로 전달 된 3 과 4를 더한 값 7을 바로 Stack 메모리에 Push 하였다. 따라서 fuction 함수를 분명 Call 하였지만 내부적으로는 3 과 4를 더하는 과정 없이 그냥 7 이라는 값을 printf 함수를 콜하며 해당 함수의 매개변수로 전달한다.

    이와같은 이유는 컴파일러 최적화 옵션에 아래와 같이 기본적으로 인라인 함수 확장 옵션이 선택 되어있기 때문이다. 즉 컴파일러는 최적화 모드로 컴파일 할 시 함수를 분석하여 만약 인라인 함수로 변경해도 괜찮다고 판단시 해당 함수는 인라인 함수로 바꾸어 버린다.  

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

    생성자 함수와 소멸자 함수  (0) 2020.04.02
    Class의 생성 과정  (0) 2020.03.31
    참조자의 내부 동작  (0) 2020.03.27
    참조형과 포인터  (0) 2020.03.26
    C++ 메모리 동적할당 및 해제 ( new & delete )  (0) 2020.03.26

    댓글

Designed by Tistory.