auto 

선언한 변수나 람다식의 타입을 컴파일러에게 자료형을 추론하도록 맡김, 실제 자료형은 컴파일 하는 동안 결정된다.

또한 일반 타입 (int, char, string 등) 초기화 하지 않은 변수를 허용하지만 auto는 초기화 하지않고서 사용 불가

포인터를 받을 때 : auto / auto *

참조를 받을 때 : auto&

auto a = 10;
auto &b = a;

a = 5;
cout << b << endl; // 5

 

범위기반 for문

std::map<int,std::string> m;

m[1] = "abc";
m[2] = "def";
m[3] = "ghi";

// std::map<int,std::string>::iterator it;
for(auto it = m.begin(); it != m.end(); it++)
    std::cout << it->first << " " << it->second << std::endl;

 

 

template

함수나 클래스를 개별적으로 다시 작성하지 않아도, 여러 자료 형으로 사용할 수 있도록 하게 만들어 놓은 틀

typename

템플릿 정의에서 알 수 없는 식별자가 형식이라는 힌트를 컴파일러에 제공합니다. 템플릿 매개 변수 목록에서 형식 매개 변수를 지정하는 데 사용

 

예제1) 여러가지 타입

template <typename T>
T Plus(T a, T b) // 같은 T타입끼리만 더한다
{
    return a + b;
}

template <>  // char* 형에 대해서 특수화
char* Plus(char* a, char* b) 
{
    size_t a_size = strlen(a);
    size_t b_size = strlen(b);

    char *str = new char(a_size + b_size + 1);

    size_t index = 0;
    for(size_t i=0; i<a_size; i++, index++)
        str[index] = a[i];
    for(size_t i=0; i<a_size; i++, index++)
        str[index] = b[i];
    str[index++] ='\0';
    return str;
}

char* Plus(char* a, char* b)   // 일반함수
{
    size_t a_size = strlen(a);
    size_t b_size = strlen(b);

    char *str = new char(a_size + b_size + 1);

    size_t index = 0;
    for(size_t i=0; i<a_size; i++, index++)
        str[index] = a[i];
    for(size_t i=0; i<a_size; i++, index++)
        str[index] = b[i];
    str[index++] ='\0';
    return str;
}

int main() {
    
    auto a = Plus(4, 2);
    cout << a << endl;    // 6 (int)
    
    auto b = Plus(3.0, 1.0);
    cout << b << endl;    // 4 (double)

    string str1 = "abc";
    string str2 = "DEF";
    auto d = Plus(str1, str2);
    cout << d << endl;    // abeDEF (string)

    auto e = Plus('0', '1'); // char + char 은 ascii값
    cout << e << endl;    // 48 + 49 = 97 = a

    auto f = Plus<char*>("abc", "DEF"); // string이 아니라 char[]로 들어가진다
    cout << f << endl;    // abcDEF (char*) 
    delete f;
    
    char ch1[] = "abc";
    char ch2[] = "DEF";
    auto g = Plus(ch1, ch2);   // 일반함수 Plus
    cout << g << endl;

    char ch3[] = "abc";
    char ch4[] = "DEF";
    auto f = Plus<char *>(ch3, ch4); // 템플릿 함수 Plus (char *재정의)
    cout << f << endl;
    
    // Plus<char *> 처럼 템플릿을 명시하면 템플릿 함수를 호출하고
    // Plus 처럼 템플릿을 생략하여 사용하면 일반함수를 호출한다.
    
    // 우선순위   일반함수 > 템플릿 함수
}

int + int , double + double , string + string 같은 인자끼리 서로 더하는 함수를 정의할때 template을 이용하면 자료형마다 함수를 중복으로 작성하지 않아도된다. 

 

또한 정의되지않은 char* + char* 이 매개변수로 들어올경우 특정 매개변수 타입으로 재정의 할수도있다. 이걸 템플릿 명시적 특수화(template explicit specialization) 라고 한다

 

컴파일 순서 

  1. 템플릿으로 만들어진 함수 템플릿 Plus가 있지만, 컴파일 시 Plus의 자료형을 알지 못하기때문에 그냥 지나친다
  2. Plus 함수를 호출하는 시점에서 일단 일반함수가 있는지 찾는다 (int, double, string, char는 구현되어있는 일반함수가 없을것이고  char* + char*일 경우에 일반함수 char* Plus(char* , char*)로 들어간다)
  3. 일반함수에서 찾지 못하였으면 함수 템플릿 Plus를 (int + int일 경우) int형 Plus템플릿 함수로 따로 만들어 준다.
  4. 만약 다른 자료형이 또 나온다면 같은 방식으로 자료형만 다른 템플릿 함수를 또 만들어준다 (double + double / string + string/ char + char)

-> 겉으로 보기에는 하나의 템플릿 함수를 범용적으로 사용하는 것 처럼 보이지만 내부적 구조를 보면 사용하는 자료형에따라 함수 오버로딩을 사용하는것과 별 차이가없다.

 

 

 

 

예제2) 여러가지 STL 

template <typename T>
void PrintFront(T &v)
{
    // T top_element = v.front();   // 에러난다 

    // 왜냐하면 STL 컨테이너들은 value_type을 가지고있고 
    // 명확한 상황이 아닌 임의의 타입T를 받아야 할 경우에 쓰라고 있다고한다
    // typename T::value_type top_element = v.front();

    // 그리고 auto가 생긴 이후부터 이렇게 어렵게 쓰지않아도 컴파일러가
    // 타입을 알아서 추론해준다.
    auto top_element = v.front();

    cout << top_element << endl;
}

int main() 
{
    vector<int> v{1,2,3};
    string str = "123";
    queue<int> q; q.push(1); q.push(2); q.push(3);
 
    PrintFront(v);
    PrintFront(str);
    PrintFront(q);
    
    // map<string, int> m; m["abc"] = 1; 
    // PrintFront(m);// 해당 STL에 front함수가 없으면 컴파일 실패
}

 

 

 

장점 단점
컴파일러가 컴파일 도중에 각 템플릿 인스턴스에 대한 코드를 만들어준다 (컴파일 속도는 느리지만 런타임 속도는 더 빠를수 있다)

  1. 변수 초기화를 놓치지 않도록 도와준다. auto는 반드시 초기화가 되어야하기 때문이다.
  2. auto는 항상 올바른 타입을 사용하는 것을 보장한다. 암시적인 형변환이 발생하지 않는다.
  3. OOP 원칙에 부합한다. 변화에 개방적이다.
  4. 타이핑이 적어지고 실수할 확률이 적어진다.
  5. 타입이 항상 오른쪽에 위치하는 일관된 코딩 스타일을 제공한다.
컴파일 타임은 비교적 느리고 템플릿 매개변수를 추가할 수록 더 느려진다

  1. auto는 만능이 아니다. const/volatile/reference에 대한 추론을 컴파일러가 자동으로 하지는 않으므로 반드시 명시해줘야 한다.
  2. long long 같은 다중 단어 타입에는 auto를 사용할 수 없다.
  3. auto의 정확한 타입을 알기 위해서는 IDE의 도움이 필요하다. 즉, 편리한 IDE가 없는 환경에서는 auto가 되려 가독성을 낮추는 결과를 낳을 수 있다.

 

+ Recent posts