본문 바로가기
프로그래밍/Modern Effective C++

Item 2. Auto 타입 추론

by drogrammer 2021. 8. 28.
반응형

C++에서 Auto 타입이 어떻게 추론되는지 알아보자. 

1. Auto

Auto 는 변수 초기화시에 자동으로 타입이 추론 되는 타입이다. 예를 들어 아래와 같은 코드는 변수 i를 int 타입으로 추론한다.

auto i = 10;
C++ 11 버전 이전에는 auto가 지역변수를 의미할 뿐이므로 주의해야 한다. 

 

2. Auto 타입 추론

기본적으로 두가지 예외를 제외하고 아래 포스팅의 템플릿 타입 추론과 동일하게 추론된다.

 

Item 1. 템플릿 타입 추론

C++ 템플릿이 타입을 어떻게 추론하는지 그 법칙을 알아보자. 1. 템플릿 일단, 템플릿이 뭐지? 라는 분을 위해 간략히 설명 하자면, 템플릿은 Generic 프로그래밍을 위해 C++ 이 제공하는 장치로, 변

drogrammer.tistory.com

 

2.1. 레퍼런스의 경우 (auto&)

기본적으로 타입의 레퍼런스로 추론된다. 단, 초기화용으로 주어진 변수가 레퍼런스일 경우 레퍼런스를 한번 더 붙이지 않는다.

int i = 1;
int& ir = i;
 
auto& ai = i;           // int& 로 추론
auto& air = ir;         // int& 로 추론
const auto& cai = i;    // int const& 로 추론
const auto& cair = ir;  // int const& 로 추론

 

2.2. 포인터의 경우 (auto*)

int i = 1;
const int* pi = &i;

auto* api = &i;   // int* 로 추론
auto* acpi = pi;  // int const* 로 추론

 

2.3. Universal 레퍼런스의 경우 (auto&&)

  • 초기화 변수가, lvalue 면 2.1. 과 동일하게 추론한다.
  • 초기화 변수가, 식, 리터럴 등의 rvalue 면 unversal 레퍼런스로 추론한다.
int i = 1;
int& ir = i;
const int ci = 1;
const int& cir = ci;

auto&& uai = i;       // int& 로 추론 (lvalue)
auto&& uair = ir;     // int& 로 추론 (lvalue)
auto&& uaci = ci;     // int const& 로 추론 (lvalue)
auto&& uacir = cir;   // int const& 로 추론 (lvalue)

auto&& ual = 10;      // int&& 로 추론 (rvalue)
auto&& uaf = i + ir;  // int&& 로 추론 (ravlue)

 

2.4. 파라미터 타입이 value 타입일 경우

초기화 변수의 레퍼런스, 상수(const), volatile 특성은 제거하고 추론한다.

int i = 1;
int& ir = i;
const int ci = 1;
const int& cir = ci;

auto ai = i;       // int 로 추론 (lvalue)
auto air = ir;     // int 로 추론 (lvalue)
auto aci = ci;     // int 로 추론 (lvalue)
auto acir = cir;   // int 로 추론 (lvalue)

auto al = 10;      // int 로 추론 (rvalue)
auto af = i + ir;  // int 로 추론 (rvalue)

 

2.5. 그 외 특이한 케이스

2.5.1. 배열 (array) 추론

초기화 변수가 배열인 경우에는 value 추론 (auto) 과 레퍼런스 추론 (auto&) 결과가 다르다. Value 추론은 배열을 포인터로 추론해 내지만, 레퍼런스로 추론하면 고정크기 배열의 레퍼런스로 추론해 낸다.

int ia[] = {1, 2, 3, 4, 5, 6};

auto aia = ia;    // int* 로 추론
auto& aiar = ia;  // int [6]& 로 추론

 

2.5.2. 함수 포인터의 경우

초기화 변수가 함수일 경우에는 2.5.1. 배열 추론과 유사하게 value 추론 (auto) 과 레퍼런스 추론 (auto&) 결과가 다르다. Value 추론은 함수 포인터로 추론해 내지만, 레퍼런스 추론은 함수 레퍼런스로 추론해 낸다.

// 추론 대상 함수
void func(int, double) {}
auto afunc = func;    // void (*)(int, double) 로 추론
auto& afuncr = func;  // void (int, double)& 로 추론

 

2.6. 예외

템플릿 추론과 방식이 다른 예외 케이스를 확인해보자.

2.6.1. 초기화 리스트 : 중괄호 초기화

중괄호를 이용하여 리스트 형태의 초기화를 할경우 std::intializer_list<T> 타입으로 추론된다.

auto ail = {10, 20, 30};    // std::initializer_list<int>

 

초기화 리스트에 동일한 타입의 값을 넣지 않으면 컴파일 에러가 발생한다.

auto aile = {10, 20, 30.0};  // error. can not deduce 'auto' type​
참고로 템플릿 타입 추론은 초기화 리스트를 지원하지 않는다.

 

2.6.2. 함수 리턴 값, 람다 파라미터 타입

auto를 함수의 리턴 값 및 람다 파라미터 타입으로 사용할 경우 템플릿 추론 방식이 사용된다. 예를 들어, 2.6.1. 초기화 리스트가 지원되지 않는다.

auto aFunc() { return {10, 20, 30}; } // error
auto aLambda = [](const auto& value) {};

aLambda({10, 20, 30}); // error
반응형

댓글