본문 바로가기

개발 Note/C++11,14 (modern C++)

effective modern c++: 명시적 형식 선언보다 auto 를 선호 하라.

반응형


항목 5, 명시적 형식 선언보다 auto 를 선호 하라.


auto라는 형식추론 방식이 C++ 11에서 도입이 되었는데요.

기존의 정적형식 절차적언어들인 C#, D, Scala, Visual Basic)등에서 auto와 비슷한 기능이 있었고, 여러 정적형식 함수형 언어들(ML, Haskel, OCaml, F#)등에서도 지원되는 기능입니다.


Perl, Python, Ruby와 같은 변수 형식을 명시적으로 지정해야 하는 경우가 아주 드문 동적 형식 언어들의 성공으로 인해 c++에서도 전격적으로 도입이 되었다고 보여집니다.


auto로 선언할 경우 힘들어지는 부분은 아마도 type이 바로 안보여서, "추측하기가 힘들다는 것, 가독성(readability)이 떨어진다." 일텐데요.

그렇지만 이런 불편보다 이익을 더 많이 얻을 수 있습니다.


1. 간단한 선언이 다시(?) 가능해졌다.

 template의 사용이 일반화되면서 type에 대한 선언부들이 복잡해지고, 심지어는 compiler에 의해 명시적 타입 지정이 힘들어질 경우도 생깁니다.


template<typename T>

void dwim(T b, T e)

{

  for(; b!=e ; ++b)

  {

    typename std::iterator_traits<T>::value_type curValue = *b;

    :

  }

}


명시적으로 변수 선언을 하려면 type 부분이 너무 길어지게 되는데, 간단한 지역 임시변수의 경우에는 auto 로 사용하는 것이 오히려 가독성과 코드 유지에 도움이 될것 같군요.



2. 타입(type)선언을 컴파일러(compiler)의 도움으로 선언하기 때문에 타입 불일치가 줄어든다.

unsigned int size = v.small_size(); // size는 int type이 됩니다. 64 bit OS에서는 64 bit, 32 bit OS에서는 32bit이 됩니다.


또 small_size()의 return type을 변경했을때, 기존 code로 작성되어있던 부분들에서 오류가 발생할 확율이 높습니다.

그리고 찾아다니면서 변경을 해줘야 겠죠.


반면,

auto size = v.small_size();  //small_size()의 return 값의 타입으로 size가 선언됩니다.

코드 수정 및 오류 확율이 줄어듭니다.


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


for(const std::pair<std::string, int>& p : m)

{

  ...

}


이 경우에, unordered_map 의 key 부분이 const 여야 합니다. 따라서 p를 std::pair<const std::string, int> 가 되어야 합니다.

프로그래머의 실수이기는 하지만, 아무튼 이 상황에서 compiler는 std::pair<const std::string, int> 를 std::pair<std::string, int>로 변환하도록 시도하게됩니다.

이 과정에서 p를 위한 임시객체를 생성하고 m으로 부터 복사를 해옵니다. 

code의 길이에 비해 상당히 복잡한 과정이 발생하게 되는 것이죠.

또 loop이 끝나는 부분에서는 임시객체가 파괴(삭제)되게 되죠.


for(const auto& p:m)

{

:

}


이와 같이 auto를 이용하여 작성을 하게 되면, 이와 같은 임시객체 생성이 발생하지 않고, m 내부의 한 요소를 가리키는 포인터를 얻게 됩니다.

효율적이고 typing도 줄어들게 됩니다.



3. 초기화 되지 않은 변수 사용이 줄어든다.

초기화 되지 않은 변수는 c++ 프로그래밍을 하면서 자주 격는 문제입니다.  이런 문제에 민감한 개발자라도 한두번은 실수 할때가 있는 그런 이슈이죠.

사소하면서도 중요한 언어적인 특성이라고 봐야겠죠.



auto를 사용 하게 되면 이런 부분들이 개선됩니다.

auto 변수는 선언과 동시에 값(타입 과 함께)이 정해져야 하기 때문에 auto 변수 자체가 초기화 되지 않을 가능성은 없습니다.

auto 를 사용할 경우 초기화가 되지 않으면 컴파일(compile) 단계에서 에러를 만나게 되기 때문이죠.

이런 사소한 실수가 줄어들게 됩니다.


다만 auto가 참조(reference)이고 이 참조가 가리키는 변수가 초기화 안되어 있을 경우는 있죠. 

이는 auto 변수의 초기화가 아니라 auto가 가리키는 변수의 초기화 문제로 봐야 하겠죠?





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


물론 auto가 만능은 아님은 당연한 것이겠죠..

명시적으로 type을 정의해서 사용하는 것이 좋겠다고 판단한다면 그렇게 하는 것이 좋습니다.


다만 , 기존의 "type을 명확히 하자!!!" 라는 보다는 "auto를 선호하자" 로 C++의 coding style을 옯겨 보는 것은 좋을 것 같군요.



발췌: [Effective modern C++  : 스콧 마이어스 지음, 류광 옮김]